网站建设198,网站 主营业务,个人备案的网站销售商品,wordpress 网站加载过慢字符串的修改我们知道C中不存在字符串这个概念#xff0c;python中的字符串在C中也是通过字符数组来实现的。我们说在C中创建一个字符数组有两种方式#xff1a;char *s1 hello world;char s2[] hello world;这两种方式虽然打印的结果是一样的python中的字符串在C中也是通过字符数组来实现的。我们说在C中创建一个字符数组有两种方式char *s1 hello world;char s2[] hello world;这两种方式虽然打印的结果是一样的并且s1、s2都指向了对应字符数组的首地址但是内部的结构确是不同的。1.char *s1 hello world;此时这个字符数组是存放在静态存储区里面的程序编译的时候这块区域就已经确定好了静态存储区在程序的整个运行期间都是存在的主要用来存放一些静态变量、全局变量、常量。因此s1只能够访问这个字符数组却不能够改变它因为它是一个常量。而char s2[] hello world;这种方式创建的字符数组是存放在栈当中的可以通过s2这个指针去修改它。2.char *s1 hello world;是在编译的时候就已经确定了因为是一个常量。而char s2[] hello world;则是在运行时才确定。3.char *s1 hello world;创建的字符数组存于静态存储区char s2[] hello world;创建的字符数组存储于栈区所以s1访问的速度没有s2快。所以我们说char *s这种方式创建的字符数组在C中是不能修改的但是我们通过ctypes却可以做到对char *s进行修改#include int test(char *s1, char s2[6]){//两种方式都进行修改s1[0] a;s2[0] a;printf(s1 %s, s2 %s\n, s1, s2);}我们还是将C文件编译成mmp.dllimport ctypesfrom ctypes import *lib ctypes.CDLL(./mmp.dll)# 我们看到无论是char *s1还是char s2[...]我们都可以使用c_char_p这种方式传递lib.test(c_char_p(bhello), c_char_p(bhello)) # s1 aello, s2 aello我们看到两种方式都成功修改了但是即便能修改我们不建议这么做。不是说不让修改而是应该换一种方式。如果是需要修改的话那么不要使用c_char_p的方式来传递而是建议通过create_string_buffer来给C语言传递可以修改字符的空间。create_string_buffercreate_string_buffer是ctypes提供的一个函数表示创建具有一定大小的字符缓存就理解为字符数组即可。from ctypes import *# 传入一个int表示创建一个具有固定大小的字符缓存这里是10个s create_string_buffer(10)# 直接打印就是一个对象print(s) # # 也可以调用value方法打印它的值可以看到什么都没有print(s.value) # b# 并且它还有一个raw方法表示C语言中的字符数组由于长度为10并且没有内容所以全部是\x00就是C语言中的\0print(s.raw) # b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00# 还可以查看长度print(len(s)) # 10当然create_string_buffer如果只传一个int那么表示创建对应长度的字符缓存。除此之外还可以指定字节串此时的字符缓存大小和指定的字节串大小是一致的from ctypes import *# 此时我们直接创建了一个字符缓存s create_string_buffer(bhello)print(s) # print(s.value) # bhello# 我们知道在C中字符数组是以\0作为结束标记的所以结尾会有一个\0因为raw表示C中的字符数组print(s.raw) # bhello\x00# 长度为6bhello五个字符再加上\0一共6个print(len(s))当然create_string_buffer还可以指定字节串的同时指定空间大小。from ctypes import *# 此时我们直接创建了一个字符缓存如果不指定容量那么默认和对应的字符数组大小一致# 但是我们还可以同时指定容量记得容量要比前面的字节串的长度要大。s create_string_buffer(bhello, 10)print(s) # print(s.value) # bhello# 长度为10剩余的5个显然是\0print(s.raw) # bhello\x00\x00\x00\x00\x00print(len(s)) # 10下面我们来看看如何使用create_string_buffer来传递#include int test(char *s){//变量的形式依旧是char *s//下面的操作就是相当于把字符数组的索引为5到11的部分换成 satoris[5] ;s[6] s;s[7] a;s[8] t;s[9] o;s[10] r;s[11] i;printf(s %s\n, s);}from ctypes import *lib CDLL(./mmp.dll)s create_string_buffer(bhello, 20)lib.test(s) # s hello satori此时就成功地修改了我们这里的bhello占五个字节下一个正好是索引为5的地方然后把索引为5到11的部分换成对应的字符。但是需要注意的是一定要小心\0我们知道C语言中一旦遇到了\0就表示这个字符数组结束了。from ctypes import *lib CDLL(./mmp.dll)# 这里把hello换成hell看看会发生什么s create_string_buffer(bhell, 20)lib.test(s) # s hell# 我们看到这里只打印了hell这是为什么# 我们看一下这个sprint(s.raw) # bhell\x00 satori\x00\x00\x00\x00\x00\x00\x00\x00# 我们看到这个create_string_buffer返回的对象是可变的在将s传进去之后被修改了# 如果没有传递的话我们知道它是长这样的。bhell\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00hell的后面全部是C语言中的\0修改之后变成了这样bhell\x00 satori\x00\x00\x00\x00\x00\x00\x00\x00我们看到确实是把索引为5到11(包含11)的部分变成了satori但是我们知道C语言中扫描字符数组的时候一旦遇到了\0就表示结束了而hell后面就是\0,因为即便后面还有内容也不会输出了所以直接就只打印了hell另外除了create_string_buffer之外还有一个create_unicode_buffer针对于wchar_t用法和create_string_buffer一样。C语言中查看字符数组的长度C语言中如何查看字符数组的长度呢有两种方法一种是通过sizeof一种是通过strlen。话说我说这个干什么算了不管了。#include #include int main() {char s[] hello world;//C语言中查看字符串的长度可以使用strlen,这个需要导入string.h头文件。strlen计算的就是字符的个数不包括\0//使用sizeof计算的结果是包含\0的所以会比strlen计算的结果多1printf(%d %d\n, strlen(s), sizeof(s) / sizeof(s[0])); // 11 12return 0;}但是我们发现字符数组的创建方式是通过char s[]这种形式如果是char *s呢#include #include int main() {char *s hello world;printf(%d %d\n, strlen(s), sizeof(s) / sizeof(s[0])); // 11 8return 0;}我们看到使用strlen计算的结果是一样的但是使用sizeof得到的结果却是不一样的。因为char *s这个s我们虽然可以使用它来打印字符数组但它本质上是一个指针一个指针在64位机器上占8个字节所以结果是8。而char s[]中的s虽然也指向字符数组的首地址但它本质上是一个数组名我们使用sizeof查看得到的结果还是字符数组中所有元素的总大小。艾玛你扯到C上面干啥。。。。。。你又不会C。。。。。。来源https://www.cnblogs.com/traditional/p/12238984.html