Cha*_*via 39 c ascii endianness
和我一起工作的实习生向我展示了他在计算机科学方面考试的关于字节序问题的考试.有一个问题显示ASCII字符串"My-Pizza",学生必须显示该字符串将如何在小端计算机的内存中表示.当然,这听起来像一个技巧问题,因为ASCII字符串不受端序问题的影响.
但令人震惊的是,实习生声称他的教授坚持认为该字符串将表示为:
P-yM azzi
Run Code Online (Sandbox Code Playgroud)
我知道这不可能是正确的.在任何机器上都不能像ASCII字符串那样表示ASCII字符串.但显然,教授坚持这样做.所以,我写了一个小C程序并告诉实习生把它交给他的教授.
#include <string.h>
#include <stdio.h>
int main()
{
const char* s = "My-Pizza";
size_t length = strlen(s);
for (const char* it = s; it < s + length; ++it) {
printf("%p : %c\n", it, *it);
}
}
Run Code Online (Sandbox Code Playgroud)
这清楚地表明字符串在内存中存储为"My-Pizza".一天后,实习生回到我身边,告诉我教授现在声称C正在自动转换地址,以正确的顺序显示字符串.
我告诉他他的教授很疯狂,这显然是错的.但是为了检查我自己的理智,我决定在stackoverflow上发布这个,所以我可以让其他人确认我在说什么.
所以,我问:谁在这里?
Hea*_*utt 28
毫无疑问,你是对的.
ANSI C标准6.1.4指定通过"连接"文字中的字符将字符串文字存储在内存中.
ANSI标准6.3.6还指定了添加对指针值的影响:
当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型.如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式.
如果归因于这个人的想法是正确的,那么当整数用作数组索引时,编译器也必须使用整数数学.许多其他谬误也会产生想象力.
该人可能会混淆,因为(不同于一个字符串初始化),多字节chacter常量如"ABCD" 被存储在endian顺序.
一个人可能会对此感到困惑的原因有很多.正如其他人在这里所建议的那样,他可能误读了他在调试器窗口中看到的内容,其中内容已被字节交换以便读取int值.
AnT*_*AnT 16
教授很困惑.为了看到像'P-yM azzi'这样的东西你需要采用一些内存检查工具,以'4字节整数'模式显示内存,同时为你提供高阶中每个整数的"字符解释"字节到低位字节模式.
当然,这与字符串本身无关.并且说字符串本身在小端机器上表示是完全无稽之谈.
Dmi*_*ant 10
如果我们谈论的是每个字符使用8位的系统,那么教授就错了.
我经常使用实际使用16位字符的嵌入式系统,每个字都是little-endian.在这样的系统上,字符串"My-Pizza"确实将被存储为"yMP-ziaz".
但只要它是一个每字符8位的系统,该字符串将始终存储为"My-Pizza",独立于更高级别架构的字节序.
你可以很容易地证明编译器没有进行这种"神奇"的转换,通过在一个不知道它传递了字符串的函数中进行打印:
int foo(const void *mem, int n)
{
const char *cptr, *end;
for (cptr = mem, end = cptr + n; cptr < end; cptr++)
printf("%p : %c\n", cptr, *cptr);
}
int main()
{
const char* s = "My-Pizza";
foo(s, strlen(s));
foo(s + 1, strlen(s) - 1);
}
Run Code Online (Sandbox Code Playgroud)
地狱,你甚至可以编译成汇编gcc -S并最终确定没有魔法.
小智 9
Endianness定义多字节值中的字节顺序.字符串是单字节值的数组.因此,每个值(字符串中的字符)在little-endian和big-endian体系结构上都是相同的,并且endianness不会影响结构中值的顺序.