0
char array[8][13];
memset (&array, 0, sizeof(array)); 
/* this is a rough example this is in a struct that is memset */

if (array[0])
{
  printf("this is valid"); /* again this code is changed but it is accessing the if */
}

Why is this entering the if can you check a two dimensional array this way? This is used to store a list of names so it is really an array of strings but the way we get the data this seems the easiest way to store it.
Do I have to check != NULL. Just checking because I don't see why this doesn't work

11
  • 1
    Welcome to StackOverflow! It is expected that you post a Minimal Reproducible Example, the shortest complete code that shows the problem. Also you might benefit by reading the Tour and How do I ask a good question? Commented Apr 9 at 18:14
  • 5
    Note that array[0] becomes a pointer to another array, and won't be NULL. Commented Apr 9 at 18:15
  • Please describe what it is that you want to check. Commented Apr 9 at 18:30
  • Is the 2D array an array of strings? Are you trying to find if any of the 8 strings is the empty string, as this contrived code seems to? If so, the first string's first character array[0][0] would be 0. Commented Apr 9 at 18:36
  • 1
    @Déjàvu no, the compiler does not "inject an address" into the array. Stop it, will you? Commented Apr 9 at 22:17

4 Answers 4

2

The way to test whether a string is empty is to check whether its first element is the terminating null byte.

Since array[0] is the string you want to test, you should test array[0][0].

if (array[0][0]) {
    printf("this is valid");
}
Sign up to request clarification or add additional context in comments.

Comments

2

Why is this entering the if…?

array is an array of 8 arrays of 13 char. So array[0] is an array of 13 char.

In if (array[0]), when the compiler sees that array[0] is an array, it automatically converts the array to a pointer to its first element. So array[0] becomes &array[0][0], the address of the first char in array[0].

Then the if tests whether this is not zero. Since the pointer pointers to an object, it is not a null pointer, so it compares not equal to zero. Therefore, execution enters the “then” clause of the if statement.

array[0] will never be NULL or any null pointer because, after the automatic conversion, it always points to an object. You cannot test whether a string contained inside the array is an empty string by testing whether the address is null.

To test whether the string is empty, test whether the first char in the array is the null character or not:

if (array[0][0])
{
    // Here the array does not contain an empty string.
}
else
{
    // Here the array contains an empty string.
}

Comments

1

I will assume you are working with strings here, and wish to check whether or not the string is “empty” — meaning a string of zero length.

Since Barmar just posted his answer as I was typing this, I will continue only by adding another way of looking at it:

char * s = array[0];  
// array[0] is a (`char[13]`),
// which decomposes into a `char*`, 
// meaning its ADDRESS is a pointer to char, which is what `s` is.

if (*s) {
    printf("%s\n", "element 0 (the first string in the array) is NOT empty");
} else {
    printf("%s\n", "element 0 (the first string in the array) is EMPTY")
}

Remember, an array of char where one of those characters has a value of '\0' (or nul) is a “string”.

An empty string is one where the first character is nul (== '\0').

An (erroneously-called) null string is one where a pointer to a string is NULL. That is to say, the string itself cannot actually be null, but a pointer can be null, so if you have a pointer to an array of characters (a pointer to a string) then that pointer can be null.

“Null” (and all variations on spelling) just means zero. So, strings are nul-terminated, meaning that the string data ends with a character value of zero. Null pointers are just pointers with an effective value of zero.


⟶ So in your example you have a two-dimensional array of characters, which can be interpreted as a one-dimensional array of strings (since a string is an array of characters). Consequently, it is not possible to have a null string, but you can have an empty string.

For this to be true, though, each row of your two-dimensional array must have a nul character in it somewhere, since each row represents a string, which must be nul-terminated (== end with a zero).

Note also that not every available character need be part of the string. You have room for 13 characters in each string, one of which must be nul, so you can store strings of lengths between 0 and 12, inclusive.

I know, it is a bit confusing at first blush, but if you keep in mind how more complex structures are built from smaller ones then it is easier to make sense of it.

2 Comments

"null string" is not so common a C phrase and ambiguous - best avoided. null pointer char *np = 0; and empty strong char es[] = ""; are better.
@chux Perhaps (and I would agree) but the term “null string” is not uncommon. I’ll rephrase, tho
1

For starters, using the unary operator & in the expression that yields the first argument in the call of memset

memset (&array, 0, sizeof(array));

does not make great sense. It is enough to write

memset ( array, 0, sizeof( array ) );

because array designators used in expressions are implicitly converted to pointers to their first element.

The two-dimensional array array is an array elements of which in turn one-dimensional arrays. So the expression array[0] yields an lvalue of the first element of the array that has the type char[13]. And again used in the condition of the if statement

if (array[0])

this array (array[0]) is converted to pointer to its first element. That is in the if statement there is checked whether the result pointer is unequal to a null pointer. But as the array in any case occupies memory then it is not a null pointer. In fact the above statement is equivalent to

if ( &array[0][0])

Instead you can write

if ( array[0][0] )

or even like

if ( **array )

20 Comments

It makes a lot of sense to use & for the first argument of memset. Please drop this anti-advice from the answer.
@tstanisl There is no any sense. The array used as the argument is implicitly converted to pointer to its first element that in turn is converted to a void pointer. If to follow your syayement then for example everybody should write char s[10]; memset( &s, 0 , sizeof( s ) ); However nobody writes such a code except possibly of you.:)
Because most C developers don't understand how arrays. really work. Using & will make memset-ing consistent for every other type. And I am not only one that uses this convention.
@tstanisl I do not see any relation between "most C developers don't understand how arrays really work" and this stupidity to write as I already showed: char s[10]; memset( &s, 0, sizeof( s ) );. It seems it is only you who does not understand "how arrays really work". Compare these two code snippets. char s[8][13]; memset( s, 0, sizeof( s ) ); and char ( *s )[13] = malloc( sizeof( char[8][13] ) ); memset( s, 0, sizeof( char[8][13] ) ); Actually the calls of memset are equivalent because the array s as an argument is implicitly converted to the type char ( * )[13].
@tstanisl Or another example for such a smart guy as you. If you have a function that calls memset then will you write as you suggest void f( char s[8][13] ) { memset( &s, 0, sizeof( char[8][13] ) ); } Or will you write void f( char s[8][13] ) { memset( s, 0, sizeof( char[8][13] ) ); }?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.