为啥我不能声明 unsigned char* test = "Some text"
Posted
技术标签:
【中文标题】为啥我不能声明 unsigned char* test = "Some text"【英文标题】:Why I can't declare unsigned char* test = "Some text"为什么我不能声明 unsigned char* test = "Some text" 【发布时间】:2012-07-01 11:10:25 【问题描述】:这在 Visual Studio 2010 中不起作用,它给了我以下错误
void main (void)
unsigned char* test = "ATGST";
编辑 1:我的问题是为什么这适用于嵌入式系统,但不适用于 PC?
但是当我把它改成:
char* test = "ATGST";
它有效。
主要是我使用 C 为嵌入式系统编写代码,并且我使用 Visual Studio 来测试一些功能,因此我不必在微控制器上实时测试它。
我需要解释一下,因为微控制器接受第一个代码。
【问题讨论】:
您为什么期望它会起作用?char
和 unsigned char
是两种不同的类型。
@ildjarn hmmmm 实际上 char 和 unsigned char 可能 是同一类型。您可以强制 VS 将 generic char 类型视为 signed char 或 unsigned char。
@Adriano : C++ 标准不同意:§3.9.1/1 "Plain char
、signed char
和 unsigned char
是三种不同的类型。" @ xsari3x : 那么那些编译器不符合要求。
对于托管(非嵌入式)系统,void main (void)
不正确。 =(嗯,大多数情况下;允许实现允许它,但没有充分的理由这样写。改用int main(void)
。对于独立(嵌入式)系统,使用编译器支持的任何东西——很可能是@ 987654332@.
@Adriano : 从char
到unsigned char
的转换必须是隐式的,但是从char*
到unsigned char*
的转换必须不,就像从@987654337 的转换一样即使int
和long
大小相同,@ 到long*
也不能。
【参考方案1】:
经过编辑以符合删除 C++ 标签和安抚嵌入标签。
首先,手头的问题是,您试图将char[]
文字传递给unsigned char*
。您不能真正将 char 等同于 unsigned
或 signed
,在这方面它有点特别。此外,字符串文字被赋予唯一的存储空间,并且永远不应该被修改。如果您要处理字符,则需要使用char[]
可以衰减到的标准 char*
。你可以强行施放它,但我不喜欢推荐这样的东西。正如其中一位 cmets 指出的那样,这样做是安全的。实际上,这实际上是一种真正安全无忧的稀有事物。
但是对于 reinterpret_casting 提供足够限定的严格答案的空间太小了,这基本上是在告诉编译器您知道自己在做什么。这可能非常危险,只有在您对手头的问题非常确定时才应该这样做。 char 通常只是通用的,甚至没有签名或未签名。由于 unsigned char 的范围比 char 更大,并且通常 char 使用有符号 char 的正子集来描述字符(或任何其他可以适合的数据),如果您的数据不在扩展的正范围内,您重新出发。但是,一定要安全地符合环境和代码。
关于入口点函数-符合编辑
既然已经确定你在嵌入式系统上工作,这意味着你的程序很可能不需要返回任何东西,所以它可以保持void main()
(它也可能需要非常不同的返回由给定的嵌入式系统指定,OP 最了解他的系统强加的要求)。在很多情况下,你可以保持 void 的原因是因为没有环境/操作系统可以安抚,没有人可以交流。但嵌入式系统也可能非常专业化,最好通过详细研究给定平台来满足要求(如果有的话)。
【讨论】:
如果语言是 C(如标记),则字符串文字的类型为char []
而不是 const char []
。 MSVC 在这里似乎不符合标准。
@R.. :我认为这个答案是在 c++
标签被编辑之前发布的。
@R.. 我只浏览 C++ 问题,只是注意到它已被删除。但是,是的,C 在这方面有所不同。我会编辑以补偿。
“我不喜欢推荐这样的东西” - 将指针投射到 (unsigned char *)
是你可以做的少数安全指针投射之一,你总是可以别名unsigned char
之类的任何东西。 Windows 始终是 2 的补码,因此您甚至不必担心 *((unsigned char*)ptr) != (unsigned char)(*ptr)
的理论可能性。尽管如此,如果它要指向一个字符串文字,那么它应该是 C 中的(const unsigned char*)
,即使该语言不需要它:如此接近推荐,但到目前为止......
您对 main() 的咆哮无关紧要,而且可能不正确。这被明确标记为嵌入式,并且 OP 正在尝试在嵌入式系统和 Windows 上运行代码。在嵌入式系统上,代码非常好,在 Windows 上,它不会在严格符合的 C 编译器上编译(VC++ 不是)。以后在评论main()的格式之前先阅读this。【参考方案2】:
首先,您需要一个const
。其次,char
!= unsigned char
,还有(唯一的)!= signed char
。
字符串字面量的类型为const char[N]
- 具有适当大小的N
,因此只能转换为const char*
。请注意,该语言有一个特殊规则,允许您隐式删除 const
但它仍然是 UB 来修改字符串文字,因此这样做是一个非常糟糕的主意。
微控制器的 C 实现在这方面是不合格的。最好简单地使用const char*
,这是正确的,而不是试图破解 VS 接受不正确的代码。
【讨论】:
@xsari3x:实际上并没有我说的那么多。如果您想了解更多信息,则必须阅读 C 标准。 问题被标记为 C,并且在 C 中字符串文字的类型为char[N]
,而不是 const char[N]
。
@DanielFischer:我很确定这在 C 中和在 C++ 中一样被弃用。无论哪种情况,删除const
都一样糟糕。
@DanielFischer 这只是一个疏忽,因为 C 标准为我们带来了称为 UB 的好东西。不是沉迷于实践。改变文字意味着什么,赋予独特的存储空间。 const-ness 是理智问题,而不是语言问题。
@DeadMG 在 C 中,没有 const
可以放在这里。当然,将字符串文字分配给const char*
会更安全,因此建议这样做,但标准规定字符串文字的类型是char[N]
,而尝试修改的类型是UB。【参考方案3】:
我相信这是将字符串分配给 unsigned char * 的情况。
好吧,当你分配一个字符串值时,它会分配与字符相关的 ASCII 值,所以你应该使用 char * 代替 unsigned char *。
如果你想分配字符串、字符以外的值,那么你的实现是正确的。
希望对你有帮助。
【讨论】:
【参考方案4】:如果您对文本使用字符类型,请使用不合格的字符。
如果您将字符类型用作数字,请使用无符号字符。 unsigned char,它至少为您提供 0 到 255 的范围。
更多信息:What is an unsigned char?
【讨论】:
【参考方案5】:我的问题是为什么这适用于嵌入式系统,但不适用于 PC?
很可能是因为您不小心在 C++ 中编译 PC 代码,它的类型检查比 C 更严格。在 C 中,无论您使用 unsigned char 还是 plain char,代码都可以正常编译。
但是,正如其他答案中所建议的,您的代码存在一些问题需要修复。如果代码需要同时在嵌入式和 Windows 上运行,您应该将其重写为:
#ifdef _WIN32
int main (void)
#else
void main (void)
#endif
const unsigned char* test = "ATGST";
【讨论】:
以上是关于为啥我不能声明 unsigned char* test = "Some text"的主要内容,如果未能解决你的问题,请参考以下文章
为啥打印 unsigned char 有时有效,有时无效?在 C 中
为啥将 unsigned char 用于 RGB 像素数据?