2014-09-30 58 views
0

我刚刚在我的大学开始了一门新课程,它没有学习所有的语法和语义(这并不算太糟)。然而,与我理解的语言(java,python)相比,一个很大的区别是指针的概念。理解C中字符串的指针

我知道:

& - Address of something 
* - value stored at the address of something 

所以,如果我有这样的字符串:

char a[] = "ABCDEF"; 

是 '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

问题是C *没有*字符串。我们只有字符数组,并按照惯例在字符串的最后一个重要字符之后放置了一个“\ 0”。 – 5gon12eder 2014-09-30 01:12:22

+0

你基本上不得不相信有这样的东西作为一个“串” - 没有。内存中可能有字节,你认为*是一个字符串,* *像字符串一样对待,但对于系统来说,它们也可能代表一个芜菁。那么,什么是字符串纯粹取决于你要跟踪。而且,由于没有什么可以调用“字符串”,因此'char *'指针只是指向RAM中某处的指针。你是否可以认为它是一个“字符串”,纯粹是你如何处理它的问题。 – 2014-09-30 01:12:48

+0

因此,在“abcd”的字符数组中,是否有一种方法可以引用“a”并通过数组增加它?谢谢 – asdf 2014-09-30 01:14:56

回答

2

在C:

  • 指针是一个地址。你几乎可以互换使用这些术语。
  • 数组变量是指向其引用的数组的第一个元素(即地址)的指针。
  • 一个字符串只是一个字符数组(或非宽字符的wchar)。

当您的代码包含像的声明:

char a[] = "ABCDEF"; 

编译器分配的整个字符阵列加上足够的存储器中的适当位置的后\0终止字节(例如,堆叠),并写入相应的字节。

记住你的变量a现在是第一个字母'A'的地址;因此你可以像指针一样使用它。例如,与*运营商访问其值(称为提领),并比较其:

*a == 'A' // commonly written as: a[0] == 'A' 

将评估为true。因此,所有以下评估为真:

*(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' 

让我知道是否需要任何额外的说明。

+0

这确实有助于这是我所希望的。谢谢!如果我在main()中声明'char a [] =“abcd”,我应该想要传入* a作为函数中的参数,然后传入地址,然后可以将其解除引用到我的数组中? – asdf 2014-09-30 01:40:02

+0

如果您想将'a'传递给另一个函数,则不应使用星号。只需用'foo(a)'调用函数即可。然后,函数'foo'将被声明为'void foo(char * a){// code goes here}'或'void foo(char a []){// code goes here}'这是相同的当然,如果你返回一个值,则替换为'void')。 – Will 2014-09-30 01:47:16

+0

顺便说一句,我真的认为你应该得到一本适当的书,以深入了解基本面。我的推荐:* C编程:现代方法* K. N. King。 – Will 2014-09-30 01:50:47

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中的某个位置标记为某种类型,并且,由于可以对指针进行任意算术运算,因此几乎可以访问任何内容(在进程地址空间中)或修改任何内容,无论是否有意义所以还是不行。

0

为了尽可能简单地把这个地:

char* str1 = "Hello world, goodbye world."; char* str2 = *str1;

您将分配给指针值str2在该位置的char值由str1指向。由于'H'的ASCII码为0x48,因此str2指向的位置变为0x48。因此,如果您解除引用str2,您将尝试在内存中的位置0x48处读取一个字节。

str1实际上位于内存中的位置0x48并且可能会工作一次,这是极不可能的,但可能的是,str1实际上位于内存中的位置0x48。但绝不应该依靠那个。

你可能在这里要做的是char* str2 = str1;。在这种情况下,str2现在指的是str1在分配时所做的相同位置(因此,如果更改str1,但将str2保持不变,则在解除引用str2时可能会出现问题,如果删除了指向的内存)。但是他们仍然指的是内存中的同一个块,因此改变str1str2的一些内容将分别推迟str2str1,或者更改指向BOTH的块的内容,或者因为内存已移动而导致无效别的地方。这取决于正在完成的操作。

如果你想要一个单独的副本,你必须复制内存块。 size_t len = strlen(str1); str2 = new char [len]; memcpy(str2,str1,len);然后,您也必须分别删除它们。 delete [] str1;不会影响str2,并且delete [] str2;不会影响str1。如果副本被克隆并存储在单独的内存块中,则它们不以任何方式连接。

这个故事的寓意是你并不真正把字符串当作实体来处理,而只是在概念上。你正在处理字符数组,就像处理整数数组或指针数组(技术上是整数数组,只是一种特定类型)。

+0

其实,没有你会从编译器得到一个错误(或者至少是一个警告),试图用'char'初始化一个char * ... – 2014-09-30 02:44:40

+0

是的,你是对的。但是,理论上...... – rsethc 2014-09-30 19:48:07