先看测试用例:
#include <stdio.h>
int main(int argc, char *argv[])
{
char *s = "hello";
char *str = "hello";
printf("compare pointers: ");
s == str ? printf("y") : printf("n"); #(1)
printf("\ncompare arguments: ");
argv[1] == argv[2] ? printf("y") : printf("n"); #(2)
printf("\nuse strcmp :");
strcmp(&argv[1], &argv[2]) ? printf("y") : printf("n"); #(3)
return 0;
}
运行结果:
$ ./a.out tmp tmp
compare pointers: y
compare arguments: n
use strcmp :y
确切的来说是想解决一些关于C和内存知识的问题:
在代码中, (1)比较的两个字符串, s和str在内存中是不同的指向char的指针, 但是他们指向的内容实际上是同一处?
(2)中比较的内容结果是不相等, "=="号比较的是所给参数的内存地址吗?
(3)的输出结果为y, 所以strcmp比较的是指针所指向的内容?
1
Andiry 2015-04-02 10:00:00 +08:00
1) s 和 str是常量指针,指向同一个地址,所以s == str
2) Yes 3) Yes |
2
zhicheng 2015-04-02 10:01:01 +08:00 via Android
1,是
2,是 3,是 |
4
g5tf87 2015-04-02 10:03:08 +08:00 2
(1)里两个hello被编译在全局数据区,应该是被编译器优化为同一个地址,所以s和str两个指针指向的内容是一样的,输出为y。
(2)里面两个参数由于函数调用,其内容先后被存入栈上,所以argv[1]和arg[2]也是指针,指向的内容是不一样的,输出为n。 (3)通过字符串比较函数,比较字符串的内容,argv[1]和arg[2]指向的内容是一样的,所以输出为y。 一点粗浅见解,如有错误,希望高手指导交流~~~ |
5
wartime 2015-04-02 10:13:59 +08:00
1. s 和 str 指向同一字符串常量, 地址值相等 (编译时确定);
2. 命令行参数不同,内存地址不同; 3. strcmp 比较两块内存里从第一个字节开始,到值为'\0'结束的字符串是否相等, 有可能溢出; 如果定义成: char s[] = "hello"; char str[] = "hello"; s != str, 此时s和str会被分配size为strlen("hello") + 1的新内存地址。 |
6
liuhaotian 2015-04-02 10:19:54 +08:00 1
是的。比较的是指向内容。
The C library function int strcmp(const char *str1, const char *str2) compares the string pointed to by str1 to the string pointed to by str2. 顺便问一下 markdown这个代码高亮是怎么做到的? |
7
herozem OP @liuhaotian 三个反单引号(数字键1左边那个), 后接bash、c、java之类的, 代码完以后另起一行再接三个反单引号
```bash ```bash #不知道嵌套会被解析成什么样子? ``` ``` |
8
mcone 2015-04-02 10:32:11 +08:00 1
如果我没记错的话,你在(1)里面的这种比较是很危险的,不同编译器在不同优化等级下面输出的结果很可能不一样(undefined behavior?)
好久没用过这个了,如有错误望楼下指出! |
9
herozem OP @wartime 我试了一下,对于
```c char s1[] = "hello"; char s2[] = "hello"; ``` 无论是使用s1 == s2 还是 strcmp(s1, s2) 结果都是n, 这其中的原因是? |
12
bugeye 2015-04-02 10:44:38 +08:00
用gcc -S xxx.c 生成汇编,然后看汇编就明白了
$ cat test.s .file "test.c" .section .rodata .LC0: .string "hello" .LC1: .string "compare pointers: " .LC2: .string "y" .LC3: .string "n" .LC4: .string "\ncompare arguments: " .LC5: .string "\nuse strcmp :" .text .globl main .type main, @function main: 看吧,只有一个"hello",所以两个指针的内容是一样的。但这种比较方法是危险的。如果生成的汇编很傻,那么结果就变了。 |
14
walleL 2015-04-02 11:04:37 +08:00
strcmp(&argv[1], &argv[2]) ? printf("y") : printf("n");
大家都没发现这一行有问题吗? 1. argv[1] 已经是指向第一个参数字符串的指针了,&argv[1] 是干嘛呢 2. strcmp() 的返回值为0时才表示相等啊 所以这样才对吧: strcmp(argv[1], argv[2]) == 0 ? printf("y") : printf("n"); |
16
hualuogeng 2015-04-02 11:10:27 +08:00
@herozem 请注意strcmp在字符串相等时,返回值是0,所以你用strcmp作为条件表达式的条件时,结果和你要的是相反的。
原文中的3,之所以相等,是因为还是比较的指针本身的值,因为不相等,所以才printf("y") 这也就能够解释你在9楼的疑问了。 |
17
hualuogeng 2015-04-02 11:11:54 +08:00
上一条回复中 "原文中的3,之所以相等" 应表述为”原文中的3,之所以输出y"
|
19
herozem OP @hualuogeng 嗯, 是这样的, 谢谢
|
20
hualuogeng 2015-04-02 11:18:36 +08:00
|
21
bugeye 2015-04-02 11:28:34 +08:00
@herozem 我觉得如果你读过汇编,就知道C语言实质上是一种可以跨平台的高级宏汇编。所以想搞清楚这些底层的问题,最好是去学汇编。
但是。。。。。按软件业的现状看,还是把时间花在能快速原型,能快点做项目的语言为佳。就算用C语言也没必要搞清楚这些东西,只要记得比较字符串strcmp是正道就行。没必要浪费时间在这些底层细节上。这些细节要想100%搞清楚,得学计算机组成原理了。 |
23
hualuogeng 2015-04-02 11:37:00 +08:00
|
24
jemyzhang 2015-04-02 11:46:04 +08:00
编译优化的关系, 优化后s和str被指向同一个地址, 所以s == str成立
|
25
ZyZyZzz 2015-04-02 12:32:43 +08:00
@hualuogeng “原文中的3,之所以输出y,是因为还是比较的指针本身的值”
比较的不是俩指针所在的内存地址嘛_(:з」∠)_? 还有这里用VS2010带的编译器编出的s和str指向的地址居然不一样…… |
26
hualuogeng 2015-04-02 13:25:51 +08:00 1
@ZyZyZzz 我们的表述不一致,实际所指是一致的,如你图中所示,实际比较的是692381和692384。
常量的编译优化是编译器实现相关的,标准上没有规定,所以总是认为s和str指向相同的内存的想法是个坑。如你所说,VS2010就和GCC实现不一样。 |
27
21grams 2015-04-02 14:13:36 +08:00
第一个是编译器优化的,不能认为永远都成立。
|
28
xieyudi1990 2015-04-02 18:26:14 +08:00 via iPhone
@Andiry s 和 str 都是变量.
|
29
linux40 2015-04-02 20:01:47 +08:00
char *str = "hello"是不好的习惯。。。至于函数有返回值的,看书吧。。。
|
30
chisj 2015-04-03 00:23:24 +08:00
《C和指针》,《C陷进和缺陷》,《C专家编程》,但是这些都不如你撸几个实际项目学的东西来得靠谱。
|