0

I asked a few questions here by now, and people don't like them, so I'll make it short.

I have tried to make a dynamically allocated array of int, and then I wanted to assign it a constant array just for test, and I couldn't do it.

When we want to create an array of chars we write: char *arr = "abc";

It didn't work like this: int *arr = {1,2,3};

but it did work when I did that: int *arr = (int[]) {1,2,3};

honestly I don't know how that cast did the job, and I was happy, until I tried to get the number of elements: int n = sizeof(arr)/sizeof(int);

  1. How does the cast make it work?

  2. How to pass that array to sizeof()?

Thank you.

2 Answers2

1

How does the cast make it work?

A string literal is a specifically supported "syntactic sugar" in C. It is an unnamed static array of char with an appended '\0'. That's why you don't need to provide type information in an initialization like this. BTW, don't attempt to modify any of its elements, it is not defined.

char *arr = "abc";

For an array of any other type you need to help the compiler to determine the correct type. So you "extend" the expression to a compound literal. It is not a cast:

int *arr = (int[]){ 1, 2, 3, };

How to pass that array to sizeof()?

sizeof is an unary operator, like - (as a negative sign for numerical values) and ~.

Its operand is an object or a type. The latter needs to be in parentheses.

But because you declared arr to be a pointer to the first element of the array, you lost the information about the array's size. So you cannot use sizeof here to obtain the number of elements pointed to by arr.

The solution is to store this information separately.

If your software design allows, you can define the array as an actual array:

int arr[] = { 1, 2, 3, };

Now you can obtain the number of elements in this array:

size_t n = sizeof arr / sizeof arr[0];
the busybee
  • 10,755
  • 3
  • 13
  • 30
  • Thank you @thebusybee, I don't know how to response privatly, but I know I can do it this way int arr[], but in this way I can't make the array bigger. – noname delete Aug 25 '22 at 13:53
  • @nonamedelete If you want to have an array of variable size, you're going to have to store the size separately, you can't use `sizeof` for that. Also, if you want to be able to resize the array, you should probably use `malloc` and friends to make dynamic allocations. – Thomas Jager Aug 25 '22 at 13:56
  • Sure. You cannot resize an array declared like the last case. Then you need to use a pointer _and another variable to trace its size_, and use `malloc` and `realloc`. But this is another issue, potentially worth a separate question, and most probably already answered multiple times here. – the busybee Aug 25 '22 at 13:57
  • 1
    In C, a string literal creates an array of type `char`, not an array of `const char`, albeit an array for which the behavior of attempting to modify it is not defined. – Eric Postpischil Aug 25 '22 at 14:03
  • @EricPostpischil, I thought that an array that I write like this "aaa" in the code itself is constant. – noname delete Aug 25 '22 at 14:18
  • @ThomasJager I know I need to use malloc and realloc, that is the point of the question, and the reason why I didn't just int arr[]. – noname delete Aug 25 '22 at 14:19
  • @thebusybee, do you know how to trace an array size from a different function without passing its size? – noname delete Aug 25 '22 at 14:21
  • @nonamedelete As it is _not defined_, any implementation is free where and how to place such an array. Many systems use read-only memory for this, though. -- No, you cannot, unless you use some special guarding value. For example, the pointer in `argv[argc]` is defined as `NULL`. – the busybee Aug 25 '22 at 14:22
  • @nonamedelete: In almost all circumstances, you should treat the array of a string literal as a constant. That is, you should not attempt to modify it. However, due to the history of C development, the **type** of the elements of the array is `char`, not `const char`, because `const` did not exist when string literals were first used. Even though the type is `char`, the C standard does not define the behavior of attempting to modify them. However, it is important to know the type because it can affect understanding error messages, diagnosing bugs, declaring routines correctly, and so on. – Eric Postpischil Aug 25 '22 at 14:30
  • @EricPostpischil thank you for the answer, but I don't understand what you thought I want to modify. nvm. – noname delete Aug 25 '22 at 14:33
  • @EricPostpischil, I feel there is too much to learn and I don't know where to find it. I looked for any information on the internet for about 6 months. I am a first year student to software engineering, but I don't think I'll move on to the next year, because I'm not good at math :/ Where can I learn? – noname delete Aug 25 '22 at 14:36
0

sizeof is NOT a (runtime) function call. Rarely are "()" needed when sizeof used correctly.

char *p = "abc"; // pointer to 4 byte read-only array
int n = sizeof *p; // "sizeof' is compiler "facility". @ compile time *p can be measured
char p[] = "abc"; // mutable 4 byte array, initialised 'a','b','c','\0'
int n = sizeof p; // can be measured at compile time
char *p = NULL; // p could be assigned to point anywhere
p = "abc";
int n = strlen( p ); // runtime function call on a pointer to a null terminated string
int arr[] = { 1, 2, 3, 4, }; // compiler secretly includes code initialising array
int n = sizeof arr/sizeof arr[0]; // compiler "knows" these dimensions, so sizeof "works"

Last example will reduce to 4 x sizeof int / sizeof int then to 4x4/4 then to 4 Effectively, this definition is the same as int n = 4;, but calculated by the accurate compiler

Repeating: sizeof is NOT a runtime function call; it is a compile time "facility" (aka "operator")

Fe2O3
  • 6,077
  • 2
  • 4
  • 20
  • @Fe203 , when I try to use sizeof without parentheses, the compiler yells at me for not having parentheses. Maybe it’s only in c? – noname delete Sep 23 '22 at 07:45
  • @nonamedelete If the code takes the size of an **object** (eg: `int a; sz = sizeof a;`) there should be no compiler complaints. To get the size of a **data type** (eg: `sz = sizeof(double)` ) then parentheses are required. In either case, it resolves to a value (of the unsigned type `size_t`). It's a compile-time thing, not a run-time thing... I can't speak to "other languages"... Cheers... – Fe2O3 Sep 23 '22 at 08:07
  • yea I got it know, Ive tried to use it for all sorts of things. Anyway, I think it’s prettier with parentheses. I shouldn’t call it sizeof() because it’s not a function though. – noname delete Sep 24 '22 at 23:25