字符指针如何作为形参进行传递

C语言 码拜 9年前 (2015-09-22) 1506次浏览
 

第一个代码(正确):

void LogPrint(const char *msg)

{

char buffer[120];

memset(buffer, 0, sizeof(buffer));

sprintf(buffer,”%s”,msg);

strcat(buffer, “\r\n”);

write_log_file(“/usr/log.txt”, FILE_MAX_SIZE, buffer, strlen(buffer));

}

第二个代码(段错误):

void LogPrint(const char *msg)

{

char *buffer;

buffer = msg;

strcat(buffer, “\r\n”);

write_log_file(“/usr/log.txt”, FILE_MAX_SIZE, buffer, strlen(buffer));

}

有时候会突然搞不懂C语言的指针, 请问, 我第二个代码  为什么会出现 段错误?

理论上 buffer = msg; 也是赋予指针 buffer 一个实际地址吧? 

#1
具体怎么调用的,从所给的代码中看不出来。

第二个代码中msg是用const修饰的,然后又用buffer赋值,最后调用了strcat,这里本身就有问题。相当于是把const修饰的指针,最后进行了修改,这明显是语义上的错误

#2
你的意思是  第二个代码中  形参 去掉 const 就不会报错了?

我觉得 buffer = msg;  这句代码本身很别扭,应该是有问题,但是我又说不出具体原因。

#3

回复2楼:

这么用,没有问题,语法上允许。我指的是,“语义”上是不对的。关键是看调用端是怎么传入参数引起的崩溃

#4
亲,很高兴为你解答这个问题。

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;

#5

回复3楼:

前端调用的话,就是 把字符串作为参数:

LogPrint(“hello, world”);

或者:

char info[] = “hello,world”;

LogPrint((char *)info);

类似这样吧。

#6

回复4楼:

光高兴没有用,说得正确才行。

char *buffer;   此时的字符指针是没有内存空间的,是一个错误的指针

—————

指针还有错误的?指针是完整的对象类型,buffer本身是一个对象,你怎么说它没有内存空间?!

buffer = msg;当将数据赋值给数组时,是直接将msg数据复制到buffer,比如buffer数组的首地址是123456

—————

这真是可怕,没听说过指针赋值会将指针所指向的数据复制过去的。即使是数组之间赋值也是不允许的。指针msg和buffer都是对象,将msg的值赋给buffer难道有错?

#7

回复4楼:

多谢你的分析。

我原先理解的是:比如: 

char *p;

char i = 1;

p = &i;

于是 p 就指向了 i    p 存的是 i 的地址;

类似的…

char *buffer;

buffer = msg   我的理解是  msg 是一个字符串的首地址, 那么 buffer 也就等于 字符串的首地址, 相当于有了内存空间;

而你的意思是 ,*buffer = *msg  才能使  buffer 等于 msg 所指向的地址?

#8

回复7楼:

你把const去掉试一下不就知道了?

#9
2楼得解释我还支持,4楼。解释错了吧
#10

回复5楼:

 

LogPrint(“hello, world”);调用第二个函数

char info[] = “hello,world”;

LogPrint((char *)info);

调用第二个函数,结果是不一样的

LogPrint(“hello, world”)中的”hello, world”字符串,分配在常量区,是不能进行写操作的。

而char info[] = “hello,world”;是分配在栈区,可以进行可操作。

所以,第一种调用会崩溃,第二种正常。

#11
const char* 无法分配的char* 编译都过不了吧
#12
const const。
#13

15分

第一个逻辑和写法都正确

第二个逻辑错误

因为你只是想 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的参数传递无关。

#14
第一段程序,唯一有点小问题的地方是,如果 msg 太长,会出现错误
#15
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));
}
#16

回复7楼:

msg是一个对象,它的值是一个字符串的首地址。buffrt=msg后,buffer对象的值也是那个字符串的首地址。

*buffer=*msg的功能等效于buffer[0]=msg[0]

#17

回复7楼:

是这个意思,而如果char *buffer在没有new一个新的内存空间一般在VC下面默认是0xCCCCCCC这些地址等等,所以你在使用这个地址的时候会出错,而如果你要使用buffer  = msg的话,那么buffer就得指向一个正确的用户空间地址。

#18

回复17楼:

另外一个问题应该我说错了,buffer = msg,当buffer是数组是,是将msg数据移动到buffer,类似于文件剪贴,而不是复制,其它的我还是坚持我的看法。

#19

 两份代码语法都没有问题, 问题应该是你传的实参,你应该是传的常量字符串做实参,

所以第一份代码没有问题,后面的strcat将添加的字符串写入了buff内存中,  第二段代码

传常量字符串时,strcat会将字符写入了常量字符串后面的内存中, 这就会造成内存越界报段错误

推荐第一份代码

#20

回复18楼:

先回去学习学习吧

#21
這個帖子怎麼越看越瘆的慌
#22

5分

LogPrint(“hello, world”);

调用第二种LogPrint,导致strcat修改常量区的内存,出错

char info[] = “hello,world”;

LogPrint((char *)info);

调用第二种LogPrint,导致strcat虽然修改的是栈上内存,但是会越界,这种行为是危险的

#23
确实是我忽略了 常量字符串 是在只读区域, 

现在明白了,多谢大家!

#24

回复22楼:

char info[] = “hello,world”;

LogPrint((char *)info);

我试了一下,确实 有 越界 提示:

*** stack smashing detected ***: ./sdata terminated

#25
第一个程序,唯一有问题的是msg 不确定多长,

所以可能会有安全问题,(缓冲区溢出)。

但从逻辑上看,不是错误,只是没有考虑代码安全。

早期,这种代码很多。

第二个程序,直接就是逻辑错误。

某些情况下,会导致运行时错误,

但是并不是所有编译器,都能保证运行时错误的,起码早期的不会。

#26
char *buffer没有指定指向是很危险的,最好先char *buffer = null,后面再分配内存

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明字符指针如何作为形参进行传递
喜欢 (0)
[1034331897@qq.com]
分享 (0)