1

When using strcmp function (in the string.h library) , passing a 2-D character array as a parameter comparison , there is a need to add the ampersand symbol like

&mainlist[i][0]

otherwise like

mainlist[i][0]

there's an error

warning: passing argument 1 of 'strcmp' makes pointer from integer without a cast [-Wint-conversion]

versus when passing 1-D character array as a parameter comparison , its enough

mainlist[i]

without ampersand symbol. How come?

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

#define FOUND 1
#define NOT 0

int main()
{
   char mainlist[5][10] = {"test1", "test2", "test3", "test4", "test5"};
   int flag, i;
   flag = NOT;
   char myname[50];
   printf("Enter ur name.\n");
   scanf("%s", myname);
   for(i = 0; i < 5; i++)
   {
      if(strcmp(mainlist[i], myname)== 0) //vs if(strcmp(&mainlist[i][0]), myname)==0)
      {
         flag = FOUND;
         printf("Your name was found welcome.\n");
         break;
        
      }
   }
   if(flag == NOT)
   {
      printf("Your name was not found .\n");
   }
}
yano
  • 4,827
  • 2
  • 23
  • 35
Steve Bob
  • 5
  • 5
  • 2
    In most situations, when using the name of an array in an expression, the array will [decay](https://stackoverflow.com/q/1461432/12149471) to a pointer to the first element of the array. Therefore, when writing the expression `mainlist[i]`, in most situations, this expression will decay to a pointer to the first element, i.e. to `&mainlist[i][0]`. – Andreas Wenzel Jul 20 '22 at 03:04
  • 3
    Elements of mainlist are chars, so `mainlist[i][0]` has `char` type, `strcmp()` expect pointer to a chars. – dimich Jul 20 '22 at 03:06
  • 3
    instead, do `#include `, do `bool flag`, and get rid of `#define FOUND` and `NOT` – yano Jul 20 '22 at 04:11
  • `a[i]` is convenient notation for `*(a+i)`, (as such, `i[a]` is also completely valid.) – Neil Jul 20 '22 at 21:28

1 Answers1

3

When using strcmp function (in the string.h library) , passing a 2-D character array as a parameter comparison , there is a need to add the ampersand symbol like: &mainlist[i][0]

Each use of an array index reduces a dimension of the array. mainlist is a 2D char array, mainlist[i] is a 1D char array, and mainlist[i][0] is a single char.

strcmp() requires its arguments to be pointers to the first char in the strings to compare, that's all that string are. mainlist[i][0] is a single char, like 't', so that won't work. &mainlist[i][0] is its address, a pointer to the first char in the string, so that works.

On the other hand, when you give an array is given as a function argument, what actually gets passed is a pointer to the first element of the array. For array mainlist[i], that's &mainlist[i][0]. Look familiar? This is presumably one of the key points you overlooked.


char mainlist[5][10] = {"test1", "test2", "test3", "test4", "test5"};

Looks like this in memory.

          1         2         3         4
01234567890123456789012345678901234567890123456789
test1_____test2_____test3_____test4_____test5_____
^
|
mainlist

Where _ represents a null byte. mainlist points at the memory containing the first character.

When you ask for mainlist[i] that says to add i * 10 to the address of mainlist and dereference it. You can literally write *mainlist + i * 10

          mainlist[1]         mainlist[3]
          |                   |
          v                   v
          1         2         3         4
01234567890123456789012345678901234567890123456789
test1_____test2_____test3_____test4_____test5_____
^                   ^                   ^
|                   |                   |
mainlist[0]         mainlist[2]         mainlist[4]

A pointer to the first character of a string is what a string is in C, a char *. Each of these are a string, a 1-D array, suitable for passing to strcmp.

mainlist[i][0] says to take the address of mainlist[i], add 0, and dereference it. The result is a char like t. This doesn't work with strcmp because it takes a pointer. The integer in "warning: passing argument 1 of 'strcmp' makes pointer from integer without a cast [-Wint-conversion]" is the char because characters are just integers and strcmp tried to use that integer as a char pointer.

&mainlist[i][0] says to make a pointer to that char, so we're back to a char * or mainlist[i].

Demonstration.

mainlist[i] is almost always preferable to &mainlist[i][0]. However, it does have its uses. There are times when you want to skip the first few characters of a string, and you can do so without copying nor modifying the string. For example, &mainlist[2][2] is "st3". It's a pointer to mainlist[2] + 2.

                      &mainlist[2][2]
                      |
                      v
01234567890123456789012345678901234567890123456789
test1_____test2_____test3_____test4_____test5_____
                    ^
                    |
                    mainlist[2]

C will read from the pointer until the null byte.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Nice answer. Too bad it includes "`mainlist` is, effectively, a `char **`". I suppose you are trying to avoid excessive technical detail, but this particular detail is one that regularly bites C neophytes. A 2D array is an array of arrays, and it decays to a pointer to an array. This is neither equivalent to nor interchangeable with a double pointer. – John Bollinger Jul 20 '22 at 04:42
  • @JohnBollinger I hear you, and I struggled with that myself. However, at this point in their learning it would just go over their head. C is fractally complicated. It throws so many new and complicated things at a new programmer that one has to resist dragging them into that fractal. Pointer decay is not necessary to get a grasp of what's happening. If you have a link to a simple explanation, link it to "effectively". – Schwern Jul 20 '22 at 05:43
  • @JohnBollinger If you have a more accurate and succinct way to explain it, please edit it in. But do be careful of the fractal. – Schwern Jul 20 '22 at 05:48
  • See what you think of that. – John Bollinger Jul 20 '22 at 14:50
  • 1
    @JohnBollinger Thank you, I tweaked it some. I made it clear that `x`, `x[i]` and `x[i][j]` all reduce the dimensions of the array; I think that's the main confusion. I wanted to say "each use of an array index dereferences the pointer", I find it illustrative think of it as `char **` to `char *` to `char`, but that isn't quite right for arrays. – Schwern Jul 20 '22 at 20:03