English 中文(简体)
• 如何通过果园** ,以履行预期一系列星座的功能
原标题:How to pass a char** to a function that expects a const array of const char pointers

如下文所示,我谨通过<代码>*char **x界定的变量,改为仅读。

参考书显示按线搜索源代码对<代码>char *x界定的变量进行直线搜索,将其通过<代码>search,作为由const int a [ ]界定的临时论点。

So I hit upon an idea that what if in the case of a string? Then I wrote the code below.

gcc, Corng and MSVC Analysis can be found here

// Linear Search

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int scanf_s(const char *format ,...); // for gcc and clang environment
// int search(const char **a, int n, char *key) {       //※[1]not allowed in c lang specification⇒NG
// int search(char * const *a, int n, char *key) {      //※[2]⇒NG
// int search(const char * const *a, int n, char *key) {    //※[3]warning occured in gcc and clang!!
// int search(char const * const *a, int n, char *key) {//※[4]same as above
// int search(const char * const a[], int n, char *key) {//※[5]same as above
// int search(const char *a[], int n, char *key) {      //※[6]I thought this was ok, but warning occured in gcc and clang!!
int search(char **a, int n, char *key) {            //in conclusion, gcc,clang and MSVC only allowing this!!
    int i = 0;

    for (i = 0; i < n; i++) {
        if (strcmp(a[i], key) == 0)
            return i;
    }
    return -1;

    /* or while style!! the reference book shows this style!!
    while (1) {
        if (i == n)
            return -1;
        if (strcmp(a[i], key) == 0)
            return i;
        i++;
    }
    */
}

int main(void) {
    char **x;
    char *ky;
    int nx;
    int idx;
    int i;

    puts("Linear Search");
    printf("How many Elements??:");
    scanf_s("%d", &nx);
    
    x = malloc(sizeof(char*) * nx);
    if (x == NULL) {
        printf("Pointer to Pointer x malloc failed!!
");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < nx; i++) {
        printf("x[%d]:", i);
        x[i] = malloc(sizeof(char) * 35);
        if (x[i] == NULL) {
            printf("Pointer Array x[] malloc failed!!
", i);
            exit(EXIT_FAILURE);
        }
        scanf_s("%s", x[i], 35);
    }

    printf("Target Value:");
    ky = malloc(sizeof(char) * 35);
    if (x == NULL) {
        printf("target value malloc failed!!
");
        exit(EXIT_FAILURE);
    }
    // Or
    // ky = calloc(35, sizeof(char));
    scanf_s("%s", ky, 35);

    idx = search(x, nx, ky);

    if (idx == -1)
        puts("no target value.");
    else
        printf("%s is in x[%d]!!
", ky, idx);

    free(ky);
    for (i = 0; i < nx; i++) {
        free(x[i]);
    }
    free(x);
    system("pause");
    return 0;
}

附有<条码>const的法典规定,通过MSVC可以在没有任何警告的情况下汇编(※ ~[6])。

因此,如何根据“<代码>search功能”这一想法来书写代码,必须接受由<代码>char **x/code>界定的变数作为仅读的理由?

最佳回答

编造者希望阵列中的座标号为const char*

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#define STRING_LENGTH 36

int scanf_s(const char *format ,...);

unsigned int search(const char* const stringArray[], unsigned int stringCount, const char* stringToSearch)
{
   for(unsigned int i = 0; i < stringCount; i++)
   {
      if(strcmp(stringArray[i], stringToSearch) == 0)
      {
         return i;
      }
   }

   return UINT_MAX;
}

int main(void)
{
   printf("Enter the count of strings: ");

   unsigned int strCount;
   scanf_s("%u", &strCount);

   char* *strArray = malloc(sizeof(char*) * strCount);
   if(strArray == NULL)
   {
       printf("Could not get memory for the string array!
");
       return EXIT_FAILURE;
   }

   for(unsigned int i = 0; i < strCount; i++)
   {
       strArray[i] = calloc(sizeof(char), STRING_LENGTH);
       if(strArray[i] == NULL)
       {
          printf("Could not get memory for the next string!
");
          return EXIT_FAILURE;
       }

       printf("Enter %uth string (%i characters at most): ", (i + 1), (STRING_LENGTH - 1));
       scanf_s("%s", strArray[i], STRING_LENGTH);
   }

   char* strToSearch = calloc(sizeof(char), STRING_LENGTH);
   if(strToSearch == NULL)
   {
      printf("Could not get memory for the string to be searched!
");
      return EXIT_FAILURE;
   }

   printf("Enter string to be searched (%i characters at most) : ", (STRING_LENGTH - 1));
   scanf_s("%s", strToSearch, STRING_LENGTH);

   unsigned int result = search((const char* const*)strArray, strCount, strToSearch);
   if(result != UINT_MAX) {
      printf("String found at index: %u
", result);
   } else {
      printf("String was not found!
");
   }

   free(strToSearch);
   for(unsigned int i = 0; i < strCount; i++)
   {
       free(strArray[i]);
   }
   free(strArray);

   return EXIT_SUCCESS;
}

I tried this code in the link you provided. When I compile and run it with gcc, Sample output is as follows:

Enter the count of strings: 3
Enter 1th string (35 characters at most): Goodbye
Enter 2th string (35 characters at most): Cruel
Enter 3th string (35 characters at most): World
Enter string to be searched (35 characters at most) : Cruel
String found at index: 1

查询here

***************** 移除********************

EDIT:我想增加一些信息。

www.un.org/Depts/DGACM/index_french.htm

<>const char* const arr[ ]与const char* const arr相同。

使用<代码>const char* const* const arr的目的是保护rr的地址、rr的内容和rr的内容。

******** *** ****** *********************************************************************************

EDIT:在发表对问题的答复后,我决定添加一个简短的讲解点。 它侧重于特性点。

We all know that pointers store just memory addresses and not data. If you declare a char* cptr;, it does not yet point to a valid memory address. So, *cptr = a ; is invalid and the compiler produces a warning for that.

int main(void)
{
    char* cptr;
    *cptr =  a ; // gcc -> warning: ‘cptr’ is used uninitialized
    printf("*cptr: %c
", *cptr);
    return 0;
}

如果你试图实施上述方案,就会导致分割法。

为了能够使用名声器,你必须首先将其指向一个有效的记忆地点,如:char* cptr = malloc(sizeof(char) * 6);。 或您可从另一个<代码>char*上指定一个有效记忆点的地址。 含有果园或str。

int main(void)
{
    char* cptr = malloc(sizeof(char));
    *cptr =  a ;
    printf("*cptr: %c
", *cptr);
    free(cptr);

    cptr = malloc(sizeof(char) * 6);
    strcpy(cptr, "Hello");
    printf("*cptr: %s
", cptr);
    free(cptr);
    
    return 0;
}

产出如下:

*cptr: a
*cptr: Hello

<代码>character阵列的长度对于char*> 因为它总是只提到第一种特性的论述,并假定在毗连空间结束时,这种扼杀是完全无效的。

在解释<代码>char*的申报和使用后,现在应当解释使用<代码>const的关键词和特征标识。

Recall that pointers can provide us 3 different values: the addresses of themselves, the addresses they point to and the data at the addresses they point to.

我们可以改变点人的位置,但我们能够改变点人的其他特性。

在最后一项方案中,你认为<代码>*cptr首先指只包含一种特性的记忆点。 之后,它被定为可以储存多达6个特性(包括生态特性)的另一地点。 这一用法是一个例子,说明如何改变协调人所指出的地址。

如果您不想点到另一个地点,则需要使用<条码>。 点名前的关键词如下:char* const cptr

int main(void)
{
    char* const cptr = malloc(sizeof(char));
    *cptr =  a ;
    printf("*cptr: %c
", *cptr);
    free(cptr);

    cptr = malloc(sizeof(char) * 6); // gcc -> error: assignment of read-only variable ‘cptr’
    strcpy(cptr, "Hello");
    printf("*cptr: %s
", cptr);
    free(cptr);
    
    return 0;
}

在上述方案中,汇编者不允许在<代码>*cptr 上指定一个新地址:cptr = malloc(sizeof(char) * 6);<*cptr在方案执行期间注明同一地点。

除了改变点人指出的地址外,你还可以改变在指定地址上的数据。 可以通过如下方式做到这一点:strcpy (cptr, “Hello”);

int main(void)
{
    char* const cptr = malloc(sizeof(char));
    *cptr =  a ;
    printf("*cptr: %c
", *cptr);
    *cptr =  b ;
    printf("*cptr: %c
", *cptr);
//  cptr = malloc(sizeof(char)); // gcc -> error: assignment of read-only variable ‘cptr’
    free(cptr);


    char* const sptr = malloc(sizeof(char) * 6);
    strcpy(sptr, "Hello");
    printf("*sptr: %s
", sptr);
    strcpy(sptr, "World");
    printf("*sptr: %s
", sptr);
//  sptr = malloc(sizeof(char) * 6); // gcc -> error: assignment of read-only variable ‘sptr’
    free(sptr);
    
    return 0;
}

如果你不赞同所评论的内容,你将获得的产出是:

*cptr: a
*cptr: b
*sptr: Hello
*sptr: World

在上述方案中,尽管您可以更改点码<>*cptr和*sptr<>/code>上标明的地址,但您可更改点码上的数据。

如果你想要保护<代码>*cptr所指明的地址上的数据,而不是该地址所指明的数据? 在以下方案中:const char* cptr 可在<代码>*newCharPtr1和上加一>。 但是,<代码>*cptr不能改动其指出的地址上的数据。

int main(void)
{
    const char* cptr;
    char *newCharPtr1 = malloc(sizeof(char));
    *newCharPtr1 =  a ;
    printf("*newCharPtr1: %c
", *newCharPtr1);
    cptr = newCharPtr1;
    printf("*cptr: %c
", *cptr);

    char *newCharPtr2 = malloc(sizeof(char));
    *newCharPtr2 =  b ;
    printf("*newCharPtr2: %c
", *newCharPtr2);
    cptr = newCharPtr2;
    printf("*cptr: %c
", *cptr);

    *cptr =  c ; // gcc -> error: assignment of read-only location ‘*cptr’

    free(newCharPtr1);
    free(newCharPtr2);
    
    return 0;
}

奇怪的是,有时Compilers可以像以下方案那样ool。

int main(void)
{
    const char* sptr;
    char* newStringPtr1 = malloc(sizeof(char) * 6);
    strcpy(newStringPtr1, "Hello");
    printf("*newStringPtr1: %s
", newStringPtr1);
    sptr = newStringPtr1;
    printf("*sptr: %s
", sptr);

    char* newStringPtr2 = malloc(sizeof(char) * 6);
    strcpy(newStringPtr2, "World");
    printf("*newStringPtr2: %s
", newStringPtr2);
    sptr = newStringPtr2;
    printf("*sptr: %s
", sptr);

    // gcc -> warning: passing argument 1 of ‘strcpy’ discards ‘const’ qualifier from pointer target type
    strcpy(sptr, "Cruel");
    // gcc -> /usr/include/string.h:141:39: note: expected ‘char * restrict’ but argument is of type ‘const char *’
    printf("*newStringPtr2: %s
", newStringPtr2);

    putchar( 
 );
    const char* const sptr2 = newStringPtr2;
    printf("*newStringPtr2: %s
", newStringPtr2);
    printf("*sptr2: %s
", sptr2);
    // gcc -> warning: passing argument 1 of ‘strcpy’ discards ‘const’ qualifier from pointer target type
    strcpy(sptr2, "What?");
    // gcc -> /usr/include/string.h:141:39: note: expected ‘char * restrict’ but argument is of type ‘const char *’
    printf("*newStringPtr2: %s
", newStringPtr2);
    printf("*sptr2: %s
", sptr2);

    free(newStringPtr1);
    free(newStringPtr2);
    
    return 0;
}

上述方案的产出是:

*newStringPtr1: Hello
*sptr: Hello
*newStringPtr2: World
*sptr: World
*newStringPtr2: Cruel

*newStringPtr2: Cruel
*sptr2: Cruel
*newStringPtr2: What?
*sptr2: What?

虽然我宣布<代码>*sptr为const char*spitr*sptr2const char* constsptr2,但strcpy()>设法在标语上修改数据。 这是你为什么要把TRIEAT WARNINGS作为ERRORS的一个明显例子。

参看你如何设计C Compiler的另一个例子,请查@dbush s 。 页: 1

注:我将在我有时间时添加<代码>char**。

问题回答

不允许将<代码>char **至const char **。 虽然允许在X类中指定一个X级点至<条码>const点,但该点在多个点位之间,仅是第一级。

其原因是,允许这种转换可能导致修改const的物体。 例如:

#include <stdio.h>

int main()
{
    const char c = 1;
    const char *p1 = &c;
    char *p2;
    char **pp1 = &p2;
    const char **pp2 = pp1;    // invalid char ** to const char ** conversion
    *pp2 = p1;                 // p2 now points to c (no warning!)
    printf("p2=%p, &c=%p
", p2, &c);  // verifies the above
    *p2 = 2;                   // modifying a const object (no warning!), UB
    printf("%d
", c);

    return 0;
}

产出:

[dbush@db-centos7 ~]$ !gcc
gcc -std=c99 -g -Wall -Wextra -o x1 x1.c
x1.c: In function ‘main’:
x1.c:9:24: warning: initialization from incompatible pointer type [enabled by default]
     const char **pp2 = pp1;    // invalid char ** to const char ** conversion
                        ^
[dbush@db-centos7 ~]$ ./x1
p2=0x7ffee5f87687, &c=0x7ffee5f87687
2

如果将<代码>pp2宣布为const char* const * const * pp2,作为*pp2 = p1;行将造成错误,则上述情形就会出现。 看来,劳动和社会保障部还做了一些额外的检查,以证明没有资格和部族。

如其他答复所述,为了实现你的愿望,你必须宣布你的参数,两点人必须:

int search(const char* const *a, int n, char *key) {

当你称职时,就投下了特定的参数:

idx = search((const char* const *)x, nx, ky);

在一旁,具有阵列类型的功能参数自动调整到点式。 此外,<条码>const char和char const系指同样的事情。

因此,这意味着:

int search(const char* const *a, int n, char *key) { //※[3]
int search(char const * const *a, int n, char *key) {//※[4]
int search(const char* const a[], int n, char* key) {//※[5]

这些意思相同:

int search(const char **a, int n, char *key) {       //※[1]
int search(const char* a[], int n, char* key) {      //※[6]

尽管禁止化学武器组织已经接受了一个答复,但我的答复是提供更多细节,说明<条码>第在职能参数中所起的作用,该参数导致不相容的点码<>警报。

Argument passing behaves like assignment1).
Let s start with basic, first underst以及 the following:

    char x =  a ;           
    const char * pc = &x;   // perfectly valid   [1]
    char * const cp = &x;   // perfectly valid   [2]

From C#202x St以及ard [6.5.16.1 Simple assignment (Constraints)]
[emphasis added]

左轮演具有原体、合格或无限定的电梯型号,(考虑到左轮操作在升值后会具有的类型)

In [1], both left 以及 right of assignment has type char 以及 the type pointed by left has all qualifiers of type pointed by right 以及 an additional qualifier const. Same with [2], except the additional qualifier is added to pointer itself, making it constant (read only). Note that, additional qualifier is allowed only for the type that pointer is directly pointing to (i.e. first level of indirection) or to the pointer itself. So, [1] 以及 [2] are perfectly valid statements.

现在来的是 警告的信息,即汇编者正在对你的案件扔下。 页: 1 基本情况是:

                a = x
               /     
  (type of a) /        (type of x)
  const char **       char **

This

    const char **

点击器是const char , i.e. Pointer to pointer to a st以及ard,(合格类别为2nd水平的间接)。

以及 this

    char **

is pointer to pointer to char type i.e. pointer to pointer to an unqualified type.

你们是否看到差异?

阅读:

    const char **   -->   pointer to this
                                       |
                                       v
                                pointer to a qualified type (const char *)

以及

          char **   -->   pointer to this
                                       |
                                       v
                                pointer to an unqualified type (char *)

差异...... 因此,汇编者正在扔下不相容的“警告”。

Compiler wouldn t have thrown warning message if the type of parameter a of search() function would be char * const * a because, then, the qualifier is added at first level of indirection i.e. to the type which a is pointing to directly 以及 not to the type which is pointed by pointer whose address a is holding (i.e. a is pointing to), like in one of the initial example statement - const char * pc = &x;, here, const is added to type (char) pointed by pc directly.

尽管如此,就某种类型而言(见char):

    char a =  z ;
    const char * p1 = &a;                    //   *p1 == a
    const char * const * p2 = &p1;           //  **p2 == a
    const char * const * const * p3 = &p2;   // ***p3 == a

    // In above pointer definition statements, qualifier added at 
    // first level of indirection

如果在间接一级,即直接点以外的一级,你具有限定性,则使用明确表述。

Based on above explanation, shown below - how to call the commented function prototypes:

  1. These are same:
    int search(const char **a, int n, char *key)
    int search(const char* a[], int n, char* key)

明确表述为非第一级间接的限定词。 你可以这样说:

search ((const char **)x, nx, ky);
  1. int search(char* const *a, int n, char *key)

在点名<代码>a直接标明的类别中添加了质量,因此不需要明确表述。 你可以这样说:

search (x, nx, ky);
  1. These are same:
    int search(const char* const *a, int n, char *key)
    int search(char const * const *a, int n, char *key)
    int search(const char* const a[], int n, char* key)

明确表述为非第一级间接的限定词。 你可以这样说:

search ((const char * const *)x, nx, ky);

页: 1 见C#202x[6.5.2.2 功能电话][着重号后加]

2 If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.





相关问题
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 ...