English 中文(简体)
C组装点
原标题:Confusing pointers in C
  • 时间:2010-01-21 11:46:24
  •  标签:
  • c
  • pointers

I have more than one doubt so please bear with me. Can someone tell me why this code fails?

#include<stdio.h>
void main(int argc,char **argv) /*assume program called with arguments aaa bbb ccc*/
{
    char **list={"aaa","bbb","ccc"};

    printf("%s",argv[1]);/*prints aaa*/
    printf("%s",list[1]); /*fails*/ 
}

我假定,它与点人有某种关系,即不明白。 i:

#include<stdio.h>
void main()
{
char **list={"aaa","bbb","ccc"};
char *ptr;
ptr=list;
printf("%s",ptr);/*this prints the first string aaa*/
    /* My second question is how do i increment the value
       of ptr so that it points to the second string bbb*/
}

What is the difference between char *list[] and char **list and in what situations are both ideal to be used? One more thing confusing me is argv special? when i pass char **list to another function assuming it would let me access the contents the way i could with argv, it also failed.

我过去曾提出过类似的问题,但似乎无法找到需要什么。 如果是的话,请人张贴相关链接。

最佳回答

您应使用char*list[]={“aa”、“bbb”、“ccc”};,而不是char **list={“aa”、“bbb”、“ccc”};。 页: 1 各位使用<代码>char**,向一个或多个点人传递功能。

  • T* x[] = array of pointers
  • T** x = pointer to pointer

P.S. Responseing to ejohn: 我只能想设立一个点人(作为实际宣布的变数,而不是作为功能参数或由单体<代码>和p;营运人:创建的临时性功能参数)。 简言之,操作是点人,手提是用户拥有的,但其指出可以按照监督厅或图书馆的需要加以改变。

在整个旧的Maceau广泛使用手套。 自2005年起,从2005年起,从2005年起,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始,从2005年起开始。 在没有虚拟记忆技术的情况下发展了本组织,唯一能够避免迅速支离破碎的办法是几乎在所有记忆分配中使用。 这使本组织能够按照需要调动记忆,以缩小差距,打开更多、相邻的免费记忆区。

事实真相是,这项战略最好只是“少了”。 有许多不利因素:

  • A common bug was when programmers would dereference the handle to a pointer, and use that pointer for several function calls. If any of those function calls moved memory, there was a chance that the pointer would become invalid, and dereferencing it would corrupt memory and possibly crash the program. This is an insidious bug, since dereferencing the bad pointer would not result in a bus error or segmentation fault, since the memory itself was still existent and accessible; it just was no longer used by the object you were using.
  • For this reason, the compiler had to be extra careful and some Common Subexpression Elimination optimizations couldn t be taken (the common subexpression being the handle dereference to a pointer).
  • So, in order to ensure proper execution, almost all accesses through handles require two indirect accesses, instead of one with a plain old pointer. This can hurt performance.
  • Every API provided by the OS or any library had to specify whether it could possibly "move memory". If you called one of these functions, all your pointers obtained via handles were now invalid. There wasn t a way to have the IDE do this for you or check you, since the moves-memory call and the pointer that became invalid might not even be in the same source file.
  • Performance becomes nondeterministic, because you never know when the OS will pause to compact your memory (which involved a lot of memcpy() work).
  • Multithreading becomes difficult because one thread could move memory while another is executing or blocked, invalidating its pointers. Remember, handles have to be used for almost all memory allocation to keep from fragmenting the heap, so threads are still likely to need access to memory via a handle even if they use none of the Mac OS APIs.
  • There were function calls for locking and unlocking the pointers pointed to by handles, however, too much locking hurts performance and fragments the heap.

我也许想再说几句。 然而,所有这些不利之处仍然比仅仅使用点数和迅速分割裂痕,特别是在只有128K的第一批Macs。 这还使人想到,为什么 Apple果完全乐于 this,然后回到发展局,一旦其整个产品项目有记忆管理单位,他们就有机会。

问题回答

首先,不要掉头.。 。 除非您的汇编者文件具体指出,它支持<条码>,避免主(<>/代码>,使用<条码>,主要(不含)或<条码>。

现在让我回下一分钟,谈谈点人和阵列之间的分歧。 首先要记住的是,阵列和点号是完全不同的东西。 你可能已经听到或读过一个阵列只是一个点;这是不正确的。 在多数情况下,一个阵列expression的型号将从“T”的“N-element range of T”改为“pointer to T”(至某一点类型)及其价值设定为阵列中第一件事时,其例外情形是,阵列的表述是sizeof或地址(&)的操作者,或阵列是用来确定另一阵列的直径。

阵列是保存T型N元件的记忆块;一个点子是保存T型单一价值的地址的顶点。 您不能给一阵标分配新的价值,即不允许:

int a[10], b[10];
a = b;

注:体字面(如“aaa”)也是阵列;类型为N-element阵列(C++的座标),N为护str的长度,加之0。 字面固定;在方案启动时分配,在方案退出之前就存在。 这些规定也是不可调和的(试图修改说明字面的内容,导致不明确的行为)。 例如,“aaa”一词的类型是静态的4个lement体。 与其他阵列一样,在多数情形下,字面从阵列类型到点式类型。 当你写文章时,你就写了类似的东西。

char *p = "aaa";

阵列“aa” decays from char [4] to char *,其价值为首个阵列的地址;address随即抄到p

但是,如果使用字面来初步确定一系列的果园:

char a[] = "aaa";

那么,这种类型没有转换;字面仍然作为阵列处理,阵列的contents被复制到a(和a被含蓄地大小,以掌握插图内容和0 决定因素)。 结果大致相当于写作

char a[4];
strcpy(a, "aaa");

当一系列类型的<代码>T a[N]是sizeof的操作者时,结果就是整个阵列的规模:N*(T)大小。 当操作地址(&)操作者操作时,结果就是整个阵列的指向者,而不是第一个要素的指点(在实践中,这些要素是相同的 Value,但类型不同):

Declaration: T a[N];  

 Expression   Type        "Decays" to  Value
 ----------   ----        -----------  ------
          a   T [N]       T *          address of a[0]
         &a   T (*)[N]                 address of a
   sizeof a   size_t                   number of bytes in a
                                        (N * sizeof(T))
       a[i]   T                        value of a[i]
      &a[i]   T *                      address of a[i]
sizeof a[i]  size_t                    number of bytes in a[i] (sizeof (T))

请注意,阵列的表述<代码>a decays to category T*,或点至T。 这与以下表述相同:<代码>&a[0]。 这两种表述都产生了阵列中第一个要素的论述。 The expression &a is of category T (*)[N], or pointer to N-element range of T, and it produceds the address of the/2008/3 within, not the first content. 由于阵列的地址与阵列第1部分的地址相同,a,&a[0]&a[0] 均产生相同的 /em>,但表达方式并非全部相同 bet>。 在试图将职能定义与职能要求相匹配时,这一点很重要。 如果您希望通过array<>,作为职能的一个参数,如:

int a[10];
...
foo(a);

因此,相应的职能定义必须相应地确定。

void foo(int *p) { ... }

收到的<条码>foo是暗中点,而不是一阵列。 请注意,您可以将其称作foo(a)foo(&a[0](或甚至foo(&v),其中v是一个简单的内变量,尽管foo正在预计会出现引起问题的阵列。 请注意,就职能参数声明而言,int a[]int *a 相同,但仅为<> /em>在此种情况下适用。 坦率地说,我想int a[ ] form负责对点人、阵列和职能进行大量混淆的思考,不应加以使用。

如果您希望通过点至阵列,以履行职务,例如:

int a[10];
foo(&a);

因此,相应的职能定义必须相应地确定。

void foo(int (*p)[10]) {...}

以及当你想提及某一具体内容时,你必须参照点名 <> <> >。 适用本说明:

for (i = 0; i < 10; i++)
  (*p)[i] = i * i;

现在请把key子扔进工程中,并给工程阵列增加第二面:

Declaration: T a[M][N];

  Expression   Type        "Decays" to  Value
  ----------   ----        -----------  ------
           a   T [M][N]    T (*)[N]     address of a[0]
          &a   T (*)[M][N]              address of a
    sizeof a   size_t                   number of bytes in a (M * N * sizeof(T))
        a[i]   T [N]       T *          address of a[i][0]
       &a[i]   T (*)[N]                 address of a[i]
 sizeof a[i]   size_t                   number of bytes in a[i] (N * sizeof(T))
     a[i][j]   T                        value of a[i][j]
    &a[i][j]   T *                      address of a[i][j]

请注意,在这种情况下,a <>/code>和a [i]都是阵容表示,因此,它们各自的阵列类型在多数情况下将降至点类型;a将从“M-element range of N-element range of T”类改为“pointer to N-element range of T”,将从“N-element range of T”改为“pointer to T”。 并且,<代码>a,&aa[0],&a[0], 和&a[0][0]将产生相同的 Values。 (阵列开始的地址),但并非全部相同的 类型。 如果你想通过一个2个阵列来履行以下职能:

int a[10][20];
foo(a);

因此,相应的职能定义必须相应地确定。

void foo(int (*p)[20]) {...}

通知说,这同向1个阵列传递一个点(除了例子中阵列的规模不同外)。 然而,在这种情况下,你将像点人一样,对点人适用一个子则。

for (i = 0; i < 10; i++)
  for (j = 0; j < 20; j++)
    p[i][j] = i * j;

在此情况下,你不必明确引用<条码>p,因为<条码>p[i]隐含着的推论(p[i]=*(p+ i)

现在请看一下更重要的表述:

Declaration: T *p;
Expression   Type    Value
----------   ----    ------
         p   T *     address of another object of type T
        *p   T       value of another object of type T
        &p   T **    address of the pointer 
  sizeof p   size_t  number of bytes in pointer (depends on type and platform,
                      anywhere between 4 and 8 on common desktop architectures)
 sizeof *p   size_t  number of bytes in T
 sizeof &p   size_t  number of bytes in pointer to pointer (again, depends
                      on type and platform)

这完全是直截了当的。 标识类型包含另一个类型T的地址;参照点码(*p)产生该地址的价值,并采用点码(&p)的地址。 产生点物体的位置(点至点)。 将<>条码/代码>适用于点值,将产生点名中的tes数,而不是点人指出的 by数。

现在,假定你已经这样做了,但幸运的是死去了。

您希望创建“array号”点子,以三个字面字标示和开标,以便你宣布为

char *list[] = {"aaa", "bbb", "ccc"};

>>>>>>>。

您通过<条码>,以履行职务,如:

foo(list);

(char * [4]) to “pointer to pointer to char” (char **), 因此,接收功能必须具有对接收功能的定义。

void foo(char **p) {...}

由于子描述是根据点算法界定的,你可以使用点码操作器as [,它是一系列<代码>char*:

for (i = 0; i < 3; i++)
  printf("%s
", p[i]);

顺便提一句,这就是:main receive argv, as a pointer to char (char **), not as an range of pointer to char. 在职能参数申报方面,a[]*/code>相同,因此,char*argv[] **argv相同。

现在,因为我似乎无法在上打字,回到工作。 (打破僵局是而不是),请利用点人和有活力地分配记忆。

如果你想在一段时间内积极分配你的名单(即,你掌握了在你名单上的多少处方),你将宣布<条码>为名单<<>>为点子,然后打电话<条码>小孔<>>,以实际分配记忆:

char **list;
size_t number_of_strings;
...
list = malloc(number_of_strings * sizeof *list);
list[0] = "aaa";
list[1] = "bbb";
list[2] = "ccc";
...

由于这些是任务,而不是初步确定,字面上的表述向点人转折,因此,我们将“aaa”、“bbb”的addresses/em>复制到list>/code>的条目。 在这种情况下,listnot一个阵列类型;它只是一个点到另一个地方(在这种情况下,从小得)分配的记忆库。 再者,由于阵列说明是根据点算法界定的,你可以将子描述操作者应用到点值,因为“list [i]char*>。 不存在任何隐性转换成担忧;如果你将它变成一项职能的话。

foo(list)

然后,职能定义将是

void foo(char **list) {...}

页: 1

pssst... 是他做的?>

Yeah,我认为他做了。

果园**x显示一系列的果园,但这可能不是你的编织品{“aaa”、“bbb”、“ccc”的记忆。 果.*x[]将造成正确代码的产生,无论汇编者如何储存一系列点子。





相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...