0

I just found out that I could use sizeof() to initiate an array but not strlen(), why is this?

char str[] = " @@ Aab, ~bccdD>> e", str2[sizeof(str)]={-1};

if I use strlen(), it would give me this error, but shouldn't the return value of sizeof be a variable too?

error: variable-sized object may not be initialized char str[] = " @@ Aab, ~bccdD>> e", str2[strlen(str)]={-1};

Øø Øø
  • 45
  • 6
  • 1
    `why is this?` Sorry to be blunt, but it's because what is says: "variable-sized object may not be initialized". You have to either remove initialization `={-1}` part or not use variable `strlen` to initialize array size. – KamilCuk Apr 18 '21 at 11:09
  • `sizeof str` is a compile-time constant value, which can be used as an array size if you want to initialize the array. `strlen(str)` is evaluated at run-time and can be used for a variable-length array which can't be initialized. Also note that `sizeof str != strlen(str)`! The `strlen` function doesn't count the string null-terminator. – Some programmer dude Apr 18 '21 at 11:14
  • `sizeof operator` is being calculated at compile time, and therefore is as a contant value. `strlen` is a function and it will be calculated at run-time. Variable length arrays are not allowed in C90. – Kfir Ventura Apr 18 '21 at 11:30
  • 2
    This is a good example why you should avoid using parentheses and preferably use `sizeof str` instead of `sizeof(str)`. That is because `sizeof` is *not a function*. – Cheatah Apr 18 '21 at 12:04
  • @KamilCuk: By saying you are blunt, you indicate you think this is obvious. It is not obvious. What is constant and what is variable is not clear. C has multiple types of constant. There are literals (where the name specifies the value, like `37`). There are *integer constant expressions*, which can have only limited operators. There are integer constant expressions used as initializers, which can have some use of address constants. There are *arithmetic constant expressions*, which can have more operands. There are const-qualified objects, which can have values initialized at run-time… – Eric Postpischil Apr 18 '21 at 12:23
  • … That is five types of “constant” right there, with varying degrees of constantness versus ability to vary. Some can vary only by changing the name. Some vary by changing the compiler or C implementation. Some vary when linking changes. Some vary when program loading changes. Some vary when run-time things change. We call them “constants,” but they are not. That means a student cannot just know what “variable-sized” means. It is not a fact of nature or logic, so it has to be taught. The rules are complex, and it is a mistake to think they are obvious. – Eric Postpischil Apr 18 '21 at 12:44

2 Answers2

1

sizeof is an operator, not a function, and with one exception its value is known at compile time. When used as an array size, it’s similar to using a constant expression like 10.

Since strlen is a function, it isn’t evaluated until run time. As of C99, you can declare an array with a runtime value as the size - these are called variable-length arrays. While useful, VLAs have some limitations, one of which is that you cannot declare them with an initializer. You would have to set the initial value using memset or something like that:

char str[] = " @@ Aab, ~bccdD>> e", str2[sizeof(str)];
memset( str2, -1, sizeof str2 );

The one exception to sizeof being evaluated at runtime is when it is used on a VLA, since the size of a VLA isn’t established until runtime.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • This does not explain the concepts correctly. The fact that `sizeof` is an operator and not a function is irrelevant; the function call operator `(` `)` is also an operator. And being an operator does not mean something can be used in an integer constant expression; `(3, 4)` is not an *integer constant expression* even though it contains only literals and simple operators and is easily evaluable at compile time. `strlen` may be evaluated at compile time. – Eric Postpischil Apr 18 '21 at 12:27
0

C 2018 6.7.9 says a variable length array may not be initialized:

The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.

C 2018 6.7.6.2 4 says that if an array is declared with a size that is not an integer constant expression, it is a variable length array:

… If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type…

Constant expressions are limited by C 2018 6.6 3:

Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.

Thus, using strlen(str) makes the array a variable length array, which you cannot initialize. I do not know the exact motivation for this prohibition, but I will note that allowing initialization of variable length arrays could require the compiler to generate more code than is typical for C definitions.

That suffices to explain the error message, but I will note that integer constant expressions are further limited by C 2018 6.6 4:

An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312