|
发表于 2017-8-17 23:13:03
|
显示全部楼层
本帖最后由 Super169 于 2017-8-18 00:27 编辑
我说过让你好好想一天, 还不明白的话, 自然会给你答案的.
如果你真的不是初学, 而且还真的是测试过, 那真的难以致信了.
当然, 有测试过, 跟测试的结果是否正确, 也有很大影响的.
你是先假定了结果去测试, 看到一个答案配合, 没考虑到巧合的因素, 就当成真理了.
所以我一直都说, 明白原因, 比知道答案重要. 你就是一个活生生的例子了.
单说你是不会服的, 那我就用程式从头解释一次吧, 全部跟你用 c-free 去测试.
(1) 问题的根源, 在於你在 8楼的胡乱总结: char cResult="";//其实类似于 char cResult=0;
我在 9楼向你提问: char cResult = ""; 为什麽一定是 0?
你在 11 楼的回应, 那个 0 的原因: 一个字符串的结尾就是要补上\0
之後你在 15楼 用程式回应了我, 以程式結果 c 的值变成 0, 去证明你的谬论. (說實在的, 我也不肯定你那個例子想證明什麼.)
其实, 我在 17楼已给你提示, 19楼再提示一次, 你就是不去试试. 还好意思说自己有试过.
如果你真有试过的话, 请问以下程式, 结果会是什麽?
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- char a = "a";
- char c = "";
- printf("%d", c);
- return 0;
- }
复制代码
这个测试, 就可以证明你说的 "一个字符串的结尾就是要补上\0", 只是把不相关的东西, 胡扯过来.
"一个字符串的结尾就是要补上\0", 这是对的, 但跟 char cResult = ""; 得到结 0 结果, 是两码子的事.
如果依你上面的说法, c 应该是 0 吧. 结果真的是 0 吗?
事实上, 严格来说应该是不肯定的结果. 但一般 常数会在一个新的 segment 去编排, 所以结果几乎是固定的.
所以, 你在 c-free 中执行, 应该也是会得到 2, 而不是 0.
因为这是常数 "" 的地址的尾数部份 (之後再解释为何是一部份).
当它是第一个常数时, 地址尾数是 0. 而你看到 0 的值, 就当成了是 zero terminate 的 \0 了.
当它是第二个常数时, 地址尾数就变成了 2 (還要看前面佔的空間, 不是固定為 2 的). 因為前面佔了 2 個位, 所以 结果就是 2 了.
如果前面是 char a = "12345";, c 的值又會變成 6 了 (這是因為 "12345" 佔了 6 個 byte, 第6 個是什麼, 你應該明白的.)
不信的话, 你可以加入 printf("%d", a); 去看看, 结果会是 0.
如果根据你 11 楼的说法, 应该是 97 ('a' 的 ascii 值), 但结果是 0.
如果还有怀疑, 可以多加几个常数, 看看它们的变化吧.
(2) 你 11楼说的: char cResult="" 就变成了char 指针变量了
我在 13楼问你时, 你在 13楼时解释: 这里就强制改变了变量类型
这是基於你对 implicit type conversion 的误解.
其实我在 14楼已解释了一次, 不想再解释了, 有兴趣请看 14楼.
现在就证明一下给你看吧.
其实 c 是严谨的语言, 在定义後变数是不会改变的, 本来就不需要什麽证明.
但既然你不慬, 只好尝试用简单方式去证明吧, 请看看以下程式:
由於 c 本身没有 typeof, 只好用 sizeof 去证明:
这里 a, b 都是 char*, 虽然有着不同的字串, 但它所占的空间是一样的, 都是 4.
而 c 虽然经过了 char c = "";, 但它所占的空间, 依然是 1, 不会变成 4.
虽然 sizeof 一样, 并不代表就是相同的 type, 但 sizeof 不一样, 就肯定是不同的了.
所以, 这就可以证明, c 不会因为被放进 "", 而变成一个指针了.
(3) 现在. 可以解释一下, 之前所说的 地址的尾数, 是什麽意思.
要了解原因, 先要知道 c 语言中, "=" 的作用.
在 c 语言中, "=" 是不会改变原来的变数的类型的.
在一般情况下, 简单同类的 "=", 就是直接把有关的值 copy 过去. int = int.
在不同类之下, 结果会怎样? 同样是简单的 copy, 但就是会把 可以放的地方填满.
这是什麽意思呢? 我尝试用以下例子解释 (为了方便讲解, 以 unsigned 的数值去看吧)
比如 unsigned char = unsigned int, 而 unsigned char 只有 1 byte, 数值是 0-255.
当 unsigned int 数值大於 255 时, 就会只 copy 1 个 byte, 由於数值是倒转记录的, 结果第一个 byte 就是数值最一个 byte 了.
這也有很多不用的理解, 可以看成是把 hex 的尾數放進去. 因為數值是用倒序去儲存, 就是由第一個 byte 開始放.
我尝试做一个例子, 给你看看吧. 如果你能看得懂每一个结果的由来, 你应该对 "=" 有多一点认识了.
9999 的 hex 是 27 0f, 尾數的一個 byte 是 0f, 所以 a 就被放進了 f 的值.
而 d 就是 b 的第一個 byte, e 是第 2 個 byte, 可以看到, 第一個 byte 是 f, 第二個是 27.
數值在記憶體上的儲存, 是倒序的. 所以數值是最尾的一個 byte, 就是儲存時第一個 byte.
這個做法, 可以看成是 強制改變了要 複製的數據了. 原本是要複制 270f, 現在變成只有 0f.
注是, 是改變要 複製的數據, 而不是改變儲存的變數. a 依然是 char, 不會變成 int.
(4) 最後, 就解释一下, 为什麽你之前那个 char c = ""; 会得到 0 的值.
首先, "" 是一个 const char*, 而一个指针的值, 就是对应的数据的存放地址.
由於 const char* 是 4 byte, 而 char 只有 1 byte. 基於 (3), 你应该明白 "=" 会怎样做吧.
就是把 (const char*) 地址的数值最一个 byte, 放进 c 去.
当 char c = ""; 是第一句程式时, 由於常量基本上会分开储存, 第一个就占了该 segment 的 0 位 (注意, 不是绝对肯定的, 可能因为某些原因, 被其他资料占了 0 位.)
所以, 当在 char c = ""; 之前, 加上 char a = "a"; 时, 第一个常量变成了 "a" 而占了 0 位, "" 就变成下一个了. 而 "a" 是字串, 有兩個 byte, 分別是 'a' 及結尾的 \0, 所以下一個常數, 就要放到 2 byte 之後了.
相信配合 (3) 对 "=" 的讲解, 你应该明白, 为什麽我说 char c = ""; 时, c 为 0 的值是地址的尾数吧.
希望你看了以上的解释, 不会再去胡扯了. 认认真真去了解 = 的作用吧.
如果还有什麽地方不明白, 又或是不相信的话. 不妨说说你的想法.
或許讓你溫習一下, 試試不執行程式, 猜猜結果是什麼, 然後再執行一次, 對比一下結果是否如你所想的吧:
- #include <stdio.h>
-
- int main(int argc, char *argv[])
- {
- char c = "a";
- char* a = "123";
- char b = "a";
- char d;
- char e;
- char f;
- d = *(&c);
- e = *a;
- printf("a: %d\n", a); // 這會是什麼? 是指針的地址
- printf("b: %d\n", b); // 這會是什麼? 是 b 現在的值?
- printf("c: %d\n", c); // 這又是什麼? 是 c 現在的值, 那 c 的值又是什麼, 為什麼跟 b 一樣呢? 看看 17樓有解釋的.
- printf("d: %d\n", d); // 這會是什麼? 同樣是 c 的值
- printf("e: %d\n", e); // 這會是什麼?
- printf("f: %d\n", f); // 這會是什麼?
- printf("sizeof(a): %d\n", sizeof(a)); // 那是一個指針的大小
- printf("sizeof(c): %d\n", sizeof(c)); // 如果 c 真的變成指針, 就會跟上面的一樣.
- printf("sizeof(f): %d\n", sizeof(f)); // 如果 c 真的變了, 怎麼跟 f 一樣的?
- return 0;
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|