- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
关于C字符串的几个问题:char*
和char[]
都是指针?
我已经了解了指针,我可以知道char*
是指针,但为什么它会自动成为一个字符串,而不仅仅是一个指向1个字符的字符指针;为什么它能保存字符串?
为什么,与其他指针不同,当您为char*
指针分配新值时,实际上是在内存中分配新空间以存储新值,而与其他指针不同,您只是替换指针指向的内存地址中存储的值?
最佳答案
指针不是字符串。
字符串是一个具有array of char
类型的常量对象,而且它还具有数组的最后一个元素是空字符'\0'
的属性,而空字符int
又是一个具有整数值char
的0
值(转换为char*
类型)。char[]
是指针,但char[]
不是。类型char[]
不是“真实”类型,而是不完整类型。C语言的指定方式是,当您定义一个具有char类型数组的具体变量(对象)时,数组的大小是以某种方式确定的。因此,没有一个变量具有类型array of N objects of type char
,因为这不是一个类型(对于给定对象)。
但是,每个char *
类型的对象都会自动升级为sizeof()
,即指向指向数组初始对象的char的指针。
另一方面,这种晋升并不总是执行的。例如,运算符char*
对an array of N chars
的结果与对pointer to char
的结果不同。在前一种情况下,给定achar*
的大小(通常每个指针的大小相同…),在最后一种情况下,给出N值,即数组的大小。
当您将函数参数声明为char[]
和char *
时,行为是不同的。由于函数无法知道数组的大小,因此可以将这两个声明视为等效声明。
实际上,您就在这里:array of N chars
是一个只指向一个字符对象的指针。但是,它可以用来访问字符串,我现在将向您解释:在第1段中。我向您展示了字符串被视为内存中的对象,对于某些N
,它的类型为char*
。这个值N足够大,允许以空字符结尾(因为所有“字符串”都应该在C中)。
那么,这是怎么回事?
理解这个问题的关键是对象(在内存中)的概念。
当您有一个字符串,或者更一般地说是一个char数组时,这意味着您已经找到了某种方式来将数组对象保存在内存中。
这个对象决定了可以安全访问的RAM内存的一部分,因为C为它分配了足够的内存。
因此,当您用一个char*
变量指向这个对象的第一个字节时,实际上您已经保证可以访问该内存位置“右边”的所有相邻元素,因为这些位置被C定义为具有上面数组的字节。
简而言之:可以访问由s1
变量指向的字节的相邻(右边)字节,它们是可以访问的有效位置,因此可以“迭代”指针来遍历这些字节,直到字符串的末尾,而不存在“风险”,因为数组中的所有字节都是内存中连续的、定义良好的位置。
这是一个复杂的问题,但它揭示了您没有理解C语言中指针、数组和字符串文本之间的关系。
指针只是指向内存中某个位置的变量。
到char的pòinter只指向一个char类型的对象。
如果指向位置的相邻字节对应于一个字符数组,则指针可以访问这些字节,因此指针可以“遍历”数组对象占用的内存字节。
字符串文字被视为char对象的数组,它隐式地添加值为0(空字符)的结束字节。
在任何情况下,T对象数组都有一个定义良好的“大小”。
字符串文本有一个附加属性:它是一个常量对象。
试着把这些概念整合到你的脑海中,找出到底发生了什么。
请我澄清一下。
附加说明:
请考虑以下代码:
#include <stdio.h>
int main(void)
{
char *s1 = "not modifiable";
char s2[] = "modifiable";
printf("%s ---- %s\n\n", s1, s2);
printf("Size of array s2: %d\n\n", (int)sizeof(s2));
s2[1] = '0', s2[3] = s2[5] = '1', s2[4] = '7',
s2[6] = '4', s2[7] = '8', s2[9] = '3';
printf("New value of s2: %s\n\n",s2);
//s1[0] = 'X'; // Attempting to modify s1
}
"not modifiable"
的定义和初始化中,我们有字符串literal
s1
,它具有常量内容和常量地址。它的地址被分配给指针
s2
作为初始化。
"modifiable"
的定义和初始化中,我们有字符串literal
s2
,它同样具有常量内容和常量地址。但是,现在发生的是,作为初始化的一部分,字符串的内容被复制到char
s2
数组中。数组
char s2[]
的大小没有指定(声明
"modifiable"
给出了一个不完整的类型),但是在初始化之后,数组的大小被很好地确定并定义为复制字符串的确切大小(加上用于保存空字符或字符串结束标记的1个字符)。
s2
用于初始化数组
<string.h>
的字节,这是可修改的。
关于c - 我不了解C字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25578012/
我开始在 Ethereum blockchain 上了解如何开发智能合约以及如何写 web-script用于与智能合约交互(购买、销售、统计......)我得出了该怎么做的结论。我想知道我是否正确理解
我正在 UIView 中使用 CATransform3DMakeRotation,并且我正在尝试进行 45º,变换就像向后放置一样: 这是我拥有的“代码”,但显然没有这样做。 CATransform3
我目前正在测试 WebRTC 的功能,但我有一些脑逻辑问题。 WebRTC 究竟是什么? 我只读了“STUN”、“P2P”和其他...但是在技术方面什么是正确的 WebRTC(见下一个) 我需要什么
我在看 DelayedInit在 Scala in Depth ... 注释是我对代码的理解。 下面的 trait 接受一个非严格计算的参数(由于 => ),并返回 Unit .它的行为类似于构造函数
谁能给我指出一个用图片和简单的代码片段解释 WCF 的资源。我厌倦了谷歌搜索并在所有搜索结果中找到相同的“ABC”文章。 最佳答案 WCF 是一项非常复杂的技术,在我看来,它的文档记录非常少。启动和运
我期待以下 GetArgs.hs打印出传递给它的参数。 import System.Environment main = do args main 3 4 3 :39:1: Coul
private int vbo; private int ibo; vbo = glGenBuffers(); ibo = glGenBuffers(); glBindBuffer(GL_ARRAY_
我正在尝试一个 for 循环。我添加了一个 if 语句以在循环达到 30 时停止循环。 我见过i <= 10将运行 11 次,因为循环在达到 10 次时仍会运行。 如果有设置 i 的 if 语句,为什
我正在尝试了解 WSGI 的功能并需要一些帮助。 到目前为止,我知道它是一种服务器和应用程序之间的中间件,用于将不同的应用程序框架(位于服务器端)与应用程序连接,前提是相关框架具有 WSGI 适配器。
我是 Javascript 的新手,我正在尝试绕过 while 循环。我了解它们的目的,我想我了解它们的工作原理,但我在使用它们时遇到了麻烦。 我希望 while 值自身重复,直到两个随机数相互匹配。
我刚刚偶然发现Fabric并且文档并没有真正说明它是如何工作的。 我有根据的猜测是您需要在客户端和服务器端都安装它。 Python 代码存储在客户端,并在命令运行时通过 Fabric 的有线协议(pr
我想了解 ConditionalWeakTable .和有什么区别 class ClassA { static readonly ConditionalWeakTable OtherClass
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 5年前关闭。 Improve this questi
我还没有成功找到任何可以引导我理解 UIPickerView 和 UIPickerView 模型的好例子。有什么建议吗? 最佳答案 为什么不使用默认的 Apple 文档示例?这是来自苹果文档的名为 U
我在看foldM为了获得关于如何使用它的直觉。 foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a 在这个简单的例子中,我只返回 [Just
答案What are _mm_prefetch() locality hints?详细说明提示的含义。 我的问题是:我想要哪一个? 我正在处理一个被重复调用数十亿次的函数,其中包含一些 int 参数。
我一直在读这个article了解 gcroot 模板。我明白 gcroot provides handles into the garbage collected heap 然后 the handle
提供了一个用例: 流处理架构;事件进入 Kafka,然后由带有 MongoDB 接收器的作业进行处理。 数据库名称:myWebsite集合:用户 并且作业接收 users 集合中的 user 记录。
你好 我想更详细地了解 NFS 文件系统。我偶然发现了《NFS 图解》这本书,不幸的是它只能作为谷歌图书提供,所以有些页面丢失了。有人可能有另一个很好的资源,这将是在较低级别上了解 NFS 的良好开始
我无法理解这个问题,哪个更随机? rand() 或: rand() * rand() 我发现这是一个真正的脑筋急转弯,你能帮我吗? 编辑: 凭直觉,我知道数学答案是它们同样随机,但我忍不住认为,如果您
我是一名优秀的程序员,十分优秀!