user-0 提问: 关于字符指针作为形参如何传递

回复:
user: user-1
content: char *buffer没有指定指向是很危险的，最好先char *buffer = null，后面再分配内存

user: user-2
content: 第一个程序，唯一有问题的是msg 不确定多长， 所以可能会有安全问题，（缓冲区溢出）。 但从逻辑上看，不是错误，只是没有考虑代码安全。 早期，这种代码很多。  第二个程序，直接就是逻辑错误。 某些情况下，会导致运行时错误， 但是并不是所有编译器，都能保证运行时错误的，起码早期的不会。

user: user-3
content: LogPrint(“hello, world”); 调用第二种LogPrint，导致strcat修改常量区的内存，出错  char info[] = "hello,world"; LogPrint((char *)info); 调用第二种LogPrint，导致strcat虽然修改的是栈上内存，但是会越界，这种行为是危险的

user: user-4
content: 這個帖子怎麼越看越瘆的慌

user: user-0
content: 引用 22 楼 zilaishuichina 的回复:LogPrint(“hello, world”); 调用第二种LogPrint，导致strcat修改常量区的内存，出错  char info[] = "hello,world"; LogPrint((char *)info); 调用第二种LogPrint，导致strcat虽然修改的是栈上内存，但是会越界，这种行为是危险的   char info[] = "hello,world"; LogPrint((char *)info);  我试了一下，确实 有 越界 提示： *** stack smashing detected ***: ./sdata terminated

user: user-0
content: 确实是我忽略了 常量字符串 是在只读区域，   现在明白了，多谢大家！

user: user-2
content: 第一段程序，唯一有点小问题的地方是，如果 msg 太长，会出现错误

user: user-2
content: 第一个逻辑和写法都正确 第二个逻辑错误 因为你只是想 log msg 而已(把字符串msg，写到文件中)，并不想修改 msg 这块内存中的任何内容。 buffer = msg  二者指向同一位置（指针的值相同，表示同一地址，而且类型也几乎相同,只有可写与不可写的区别）  strcat(buffer, "\r\n"); 向msg 后面添加 "\r\n" 回车换行符， 这和这段程序的逻辑严重背离 从参数看 const char * msg  表示不希望修改字符串msg的内容 从   buffer = msg  strcat(buffer, "\r\n");  看 又修改了字符串msg 的内容 代码的逻辑是有问题的  上面这个逻辑错误，是程序本身的功能设计错误 不符合，这段程序要实现的目标，不是报错的直接原因  至于出现段错误，是因为 msg 对应的实参本身，指向的内容，也是不可改写，例如是个字符串字面值（串常量）， 这种数据，有时候会分配在只读区（段），所以就会在运行时，报出段错误。  C参数传递，不论是指针，还是其他数据，都是值传递，实参复制（可能有类型提升等情况）到形参中 但是传递指针，我们可以修改 指针指向的内容，因为这个 实参和形参指向同一个位置。 这是指针的性质，功能，和C的参数传递无关。

user: user-5
content: 引用 7 楼 teachin88 的回复:[quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间； 而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？[/quote]  msg是一个对象，它的值是一个字符串的首地址。buffrt=msg后，buffer对象的值也是那个字符串的首地址。 *buffer=*msg的功能等效于buffer[0]=msg[0]

user: user-6
content: void LogPrint(const char *msg) //msg 指向代码段 只读 | (可能，具体看你调用情况，msg分配足够内存) { char *buffer; buffer = msg; strcat(buffer, "\r\n"); write_log_file("/usr/log.txt", FILE_MAX_SIZE, buffer, strlen(buffer)); }

user: user-7
content: 引用 18 楼 momollll 的回复:[quote=引用 17 楼 momollll 的回复:] [quote=引用 7 楼 teachin88 的回复:] [quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？    [/quote] 是这个意思，而如果char *buffer在没有new一个新的内存空间一般在VC下面默认是0xCCCCCCC这些地址等等，所以你在使用这个地址的时候会出错，而如果你要使用buffer  = msg的话，那么buffer就得指向一个正确的用户空间地址。[/quote] 另外一个问题应该我说错了，buffer = msg,当buffer是数组是，是将msg数据移动到buffer，类似于文件剪贴，而不是复制，其它的我还是坚持我的看法。[/quote]  先回去学习学习吧

user: user-8
content: 两份代码语法都没有问题， 问题应该是你传的实参，你应该是传的常量字符串做实参， 所以第一份代码没有问题，后面的strcat将添加的字符串写入了buff内存中，  第二段代码 传常量字符串时，strcat会将字符写入了常量字符串后面的内存中， 这就会造成内存越界报段错误 推荐第一份代码

user: user-9
content: 引用 17 楼 momollll 的回复:[quote=引用 7 楼 teachin88 的回复:] [quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？    [/quote] 是这个意思，而如果char *buffer在没有new一个新的内存空间一般在VC下面默认是0xCCCCCCC这些地址等等，所以你在使用这个地址的时候会出错，而如果你要使用buffer  = msg的话，那么buffer就得指向一个正确的用户空间地址。[/quote] 另外一个问题应该我说错了，buffer = msg,当buffer是数组是，是将msg数据移动到buffer，类似于文件剪贴，而不是复制，其它的我还是坚持我的看法。

user: user-9
content: 引用 7 楼 teachin88 的回复:[quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？    [/quote] 是这个意思，而如果char *buffer在没有new一个新的内存空间一般在VC下面默认是0xCCCCCCC这些地址等等，所以你在使用这个地址的时候会出错，而如果你要使用buffer  = msg的话，那么buffer就得指向一个正确的用户空间地址。

user: user-10
content: const const。。。。。。

user: user-11
content: const char* 无法分配的char* 编译都过不了吧

user: user-12
content: 引用 5 楼 teachin88 的回复:[quote=引用 3 楼 jiqiang01234 的回复:] [quote=引用 2 楼 teachin88 的回复:] 你的意思是  第二个代码中  形参 去掉 const 就不会报错了？  我觉得 buffer = msg;  这句代码本身很别扭，应该是有问题，但是我又说不出具体原因。 这么用，没有问题，语法上允许。我指的是，“语义”上是不对的。关键是看调用端是怎么传入参数引起的崩溃[/quote]   前端调用的话，就是 把字符串作为参数：  LogPrint(“hello, world”);  或者：  char info[] = "hello,world"; LogPrint((char *)info);  类似这样吧。  [/quote]  LogPrint(“hello, world”);调用第二个函数 与 char info[] = "hello,world"; LogPrint((char *)info); 调用第二个函数，结果是不一样的  LogPrint(“hello, world”)中的"hello, world"字符串，分配在常量区，是不能进行写操作的。 而char info[] = "hello,world";是分配在栈区，可以进行可操作。  所以，第一种调用会崩溃，第二种正常。

user: user-13
content: 2楼得解释我还支持，4楼。。。解释错了吧

user: user-7
content: 引用 7 楼 teachin88 的回复:[quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？    [/quote] 你把const去掉试一下不就知道了？

user: user-0
content: 引用 4 楼 momollll 的回复:亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？