我刚开始在我的大学开设一个新课程,它有点直接进入C语言而没有学习所有的语法和语义(这不是很难接受)。然而,与我所理解的语言(java,python)相比,一个很大的区别是指针的概念。
我知道:
& - Address of something
* - value stored at the address of something
所以,如果我有一个像:
这样的字符串char a[] = "ABCDEF";
' a'有一个与之关联的地址(& a)如果我这样做(* a)它是否引用整个字符串? '数组中的第一个字符' (A)?
认为看到它是一个char []的想法,字符串中的每个字符都有自己的地址吗?
我的最终目标是编写一个可以操作指针的函数,以便在一个字符串中找到与第二个字符串中的字符匹配的第一个字符。
我是否在正确的轨道上?请注意,这是所有伪代码,因为我仍在尝试学习C语法
#include <stdio.h>
int main() {
create address to 'a'
create address to 'b'
make 'a' a string like "abcdefg"
make 'b' a string like 'b'
call findMatch(a,b); //pass in both to a function
return 0; // I know I have to have this at the end
}
void findMatch(char a, char b){
Retrieve the pointer to the first character in the 'a' string
Increment through 'a' to see if it matches the dereferenced b
If 'a' contains 'b' print its in the string as well as the address of the location in 'a'
}
example run - findMatch("abcdef","f") gives a print statement that says 'f' is in 'abcdef' and the address location of 'f'
我已经读过在C中使用字符串函数构建库但是我想自己操纵指针来学习。
由于
答案 0 :(得分:2)
在C:
当您的代码包含如下声明时:
char a[] = "ABCDEF";
编译器为整个字符数组分配足够的内存,并在适当的位置(例如堆栈)分配尾随的\0
终结符字节,并相应地写入字节。
请记住,您的变量a
现在是第一个字母'A'的地址;因此你可以像指针一样使用它。例如,使用*
运算符(称为解除引用)访问其值并进行比较:
*a == 'A' // commonly written as: a[0] == 'A'
将评估为真。因此,以下所有评估也都是正确的:
*(a + 1) == 'B' // commonly written as: a[1] == 'B'
*(a + 2) == 'C' // commonly written as: a[2] == 'C'
*(a + 3) == 'D' // commonly written as: a[3] == 'D'
*(a + 4) == 'E' // commonly written as: a[4] == 'E'
*(a + 5) == 'F' // commonly written as: a[5] == 'F'
*(a + 6) == '\0' // commonly written as: a[6] == '\0'
如果需要进一步澄清,请与我们联系。
答案 1 :(得分:0)
考虑到在C中,所有RAM都是一个巨大的char
数组。实际上没有(实质性的)将一个概念实体与另一个概念实体分开。
您可以在RAM中将字符串作为字节H o w . n o w . b r o w n . c o w (zero byte)
,然后在字母0x01 0x02 0x03 0x04
之后立即表示我的退休帐户中的余额。如果你把字符串更新为“现在如何使用黄牛”,那么你将在我的退休余额上写下“牛”,我会在贫民窟(如果我不在那里)。 (虽然实际上“牛”可能会有所改善。)
RAM是一个巨大的char
数组,任何类型的指针都只是指向该数组的指针。没有什么“标记”RAM中的位置是一种类型或另一种类型,并且,鉴于您可以对指针执行任意算术,您几乎可以访问任何内容(在您的进程地址空间内)或修改任何内容,无论它是否有意义是不是。
答案 2 :(得分:0)
尽可能简单地说明这一点:
char* str1 = "Hello world, goodbye world.";
char* str2 = *str1;
您将在str2
指向的位置为指针值char
分配str1
值。由于'H'
为0x48
,因此str2
指向的位置变为0x48
。因此,如果取消引用str2
,您将尝试在内存中的位置0x48
读取一个字节。
str1
实际上位于内存中0x48
的位置,并且可能会有效,但这种可能性极小。但绝不应该依赖那个。
您在此处的意思是char* str2 = str1;
。在这种情况下,str2
现在指的是str1
执行UPON ASSIGNMENT的相同位置(因此,如果您更改str1
但保持str2
不变,则在解除引用时可能会遇到问题{ {1}}如果你已经删除了指向的内存)。但它们仍然指的是内存中的相同块,因此更改str2
或str1
的内容将分别抛出str2
或str2
,或者更改内容阻止BOTH指向或使一个无效,因为内存已被移动到其他地方。这取决于正在进行的操作。
如果需要单独的副本,则必须复制内存块。 str1
然后,您还必须单独删除它们。 size_t len = strlen(str1); str2 = new char [len]; memcpy(str2,str1,len);
不会影响delete [] str1;
,str2
也不会影响delete [] str2;
。如果将副本克隆到单独的内存块中,则它们不会以任何方式连接。
故事的道德之处在于,你并不是真正将字符串作为实体来处理,而只是在概念上。您正在处理字符数组,就像处理整数数组或指针数组(技术上是整数数组,只是特定类型)。