函数参数为char * ,直接传入常量字符串(如"hello"),为何编译器能通过?
#include <string.h>
void fun(char *str, int n)
{
strncpy(str, "world", n);
}
int main()
{
const char *a = "aaaaa"
fun("hello", 5); // 为何编译器这里不出错?
fun(a, 5); // 这里编译器会报错!
return 0;
}
[解决办法]
"hello"其实 是const char [6]="hello";
可以当成const char*类型来使用
所以类型不匹配
[解决办法]
你的代码两个调用都是错误的
第一个虽说编译过去了,但运行的时候会错误的
第二个const char* 到char*是需要强制转换的
[解决办法]
你在const char *a = "aaaaa"
后加上 ;===========〉const char *a = "aaaaa" ;
然后把fun(char *str, int n)========>
void fun(const char *str, int n)
这是因为类型转换的问题
fun("hello",5),这里有个隐式拷贝,总是const
[解决办法]
两者都不报错,第二个有waring--因为是常量且类型不一。
两者都是有错误的:
错误1:
void fun(char *str, int n)
{
strncpy(str, "world", n);
} 就算能运行成功也不会有任何结果的,因为str为值传递,函数返回后其,参数的值不会改变!
错误2:
fun第一个参数应是可修改的地址(数组等),而不是不可写的常量字符区地址。
[解决办法]
char *a = "aaaaa" ;
如果你写这样的代码,那么编译器就会认为是合法的,自动进行了一个隐式转换.
这样的代码合法,但不对,引起的问题就是程序可能down掉
[解决办法]
我认为是这样的:
const char *a = "aaaaa"; 这一句你假如换成char *a = "aaaaa";
那么编译没问题,但是运行时会像楼上各位所说会down掉,因为编译的时候只会进行语法与类型安全检查,运行时错误并不会暴露.
对于你说fun("hello", 5);为什么编译不报错,其实你可以把它这样理解,程序会为hello建立一个临时变量temp,那这个程序就相当于char *temp="hello";那就编译没问题了,但是运行时还是会down掉!!!
[解决办法]
再详细点.首先const char *a = "aaaaa";fun(a, 5); 这时编译器会报cannot convert parameter 1 from 'const char *' to 'char *',类型错误.
fun("hello", 5);我上面已经说了:程序会为hello建立一个临时变量temp.
程序相当于:char *temp="hello"; fun(temp, 5); 所以编译时进行类型检查时是不会出错的!
[解决办法]
做了一个隐性的类型转换 (char*)const char*,别这么干,程序会死掉
[解决办法]
段错误?
//就如同:
main()
{
char *p="123";
*p='a';
printf(p);
}
编译器也不会报错,(甚至没有warring)。但是对常量区内存的操作是非法的。行为是未定义的。结果也是不可知的。
[解决办法]
#include <string.h > void fun(char *str, int n) { strncpy(str, "world", n); } int main() { const char *a = "aaaaa"; fun("hello", 5); // 为何编译器这里不出错? 因为"hello"的类型是 char* 类型匹配,所以不报错 fun(a, 5); // 这里编译器会报错! 因为 类型不匹配,一个char* str 一个是const char* return 0; }
[解决办法]
首先,让我们看一下这个函数:
void fun( int a )
{
...
}
我们这样调用并不认为它会有什么错:
fun( 10 );
为什么编译不出错呢?10可是 常量啊,而函数fun要求的可是 int a 而不是 const int a 啊。
难道编译器把 常量的10强制类型转换成 int a 而不是 const int a了?
大家知道,由int 转换成 const int没有问题,但为什么这里是把const int 转换成 int也不报错呢?
原因我也不知道。但据我猜测,因为这是 值传递 ,故 int
和 const int 没有区别。所以编译器是允许的。
再来看我们现在讨论的问题。
实际上,"Hello"是字符串常量,这个大家都知道,但字符串常量的本质是什么呢?是指向一串字符的指针常量,而不是很多人相当然地认为的“指向内容不变的字符串的指针变量”。换句话说,是char * const 而不是 const char *,也不是 char const *。后两者是相同的。
下面我们分析一下问题中出现的三种字符串指针的声明:
1. const char *a = "aaaaa"; 内容不可变,指针可变
2. "hello"即 char * const temp; 内容可变,指针不可变
3. void fun(char *str, int n); 内容可变,指针可变
显然,1中的声明不满足3的要求。因为const不能变为非const。但为什么2中的const就能变为非const呢?这就如我们已开始提到的作为const int的10为什么能变为非const的int呢?
原因还是据我猜测。因为这是值传递。虽然函数要求传来的是个指针,但这个指针是值传递过来的,我们在fun中对str这个指针的赋值、加减乘除以及所有运算都不会影响到实参的实际数值。所以,是不是const也就不重要了,于是乎,编译器给了我们这个方便,即在值传递的情况下,可以直接帮我们把const的变成非const。
但对指针所指向的内容,编译器可不能这么大方了。fun要求传进来的指针所指向的内容是可以被改变的,而指针a并不能承诺它指向的内容是可被改变的。所以编译器拒不接受也是情有可原的。
大家说,是不是这个理儿?