关于C语言中char*与const char*别名规则及相关未定义行为的技术问询
关于C语言中char与const char别名规则及相关未定义行为的技术问询
嘿,这个问题问得特别精准,刚好触碰到了C语言严格别名规则里容易让人迷糊的细节点!咱先把这个问题拆开来一步步说清楚。
首先你已经搞懂了:不同类型的左值别名访问会导致未定义行为,那const/非const限定符的差异会不会触发同样的问题?答案是不会,你的这段代码里的return *b完全不属于未定义行为,原因如下:
先明确严格别名规则里的关键例外
C语言的严格别名规则确实限制了不同类型的左值访问同一个对象,但它特意留了几个合法的例外,其中就包括:
- 允许用带有
const/volatile/const volatile限定符的、与对象类型兼容的左值来访问对象。
换句话说,char*和const char*本质上指向的是同一个底层类型char,只是后者多了一个“不能通过该指针修改对象”的限定——这种限定符的差异不属于“不兼容类型”,完全符合别名规则的合法范围。
针对你的代码具体分析
看你给出的代码:
char func(char *a, const char *b) { *a = '0'; return *b;//undefined behavior? } int main() { char a = 5; return (int)func(&a, &a); }
- 第一步:
*a = '0'是通过char*修改了main里定义的普通char对象,这完全合法——因为对象本身并不是const的,只是传入的b指针带有const限定,不影响对象本身的可修改性。 - 第二步:
return *b是通过const char*读取同一个char对象,这也完全符合规则:const char*和对象的实际类型char是兼容的,只是多了const限定,不属于严格别名规则禁止的情况。
顺便提一下真正会触发UB的情况
要是你把代码改成这样,才会出问题:
char func(char *a, const char *b) { *a = '0'; // 这里是未定义行为! return *b; } int main() { const char a = 5; // 对象本身是const的 return (int)func((char*)&a, &a); // 强制转换去掉const }
这种情况下,你通过非const指针修改了一个本身被声明为const的对象,这才是标准明确规定的未定义行为——和别名规则无关,而是违反了const对象的不可修改性。
内容来源于stack exchange
相关产品推荐
相关产品推荐

