Is there any way to initialize an array without brackets? - arrays

I have the question if there is any way to initialize an array with multiple elements without brackets, for example:
int a[5] = {1,2,3,4,5};
Since *(a + 5) equals with a[5] , why i cannot initialize with:
int *(a + 5) = {1,2,3,4,5};
it gives me the error: expected ')' before '+' token.

The equivalence of E1[E2] and *(E1 + E2) only applies to an expression. What you have is a declaration which has different syntax rules.
So you need to use this syntax:
int a[5] = {1,2,3,4,5};

Replacing a[5] with *(a + 5) does not work in declarations or definitions.
If you really want to avoid square brackets (to win a bet I assume), here are 2 contorted but standard complying solutions:
Using trigraphs: int a??(5??) = {1,2,3,4,5};
Using digraphs: int a<:5:> = {1,2,3,4,5};
More information can be found in Digraphs and Trigraphs.
You can even write a fragment that will compile on recent compilers where trigraphs are disabled and digraphs supported:
// trick: the comment spans to the next line if trigraphs are enabled
#define TRIGRAPHS_DISABLED 1 //??/
-1
#if TRIGRAPHS_DISABLED
int a<:5:> = {1,2,3,4,5};
#else
int a??(5??) = {1,2,3,4,5};
#endif

This
int *(a + 5) = {1,2,3,4,5};
just is an invalid declaration because in the parentheses there is used the expression ( a + 5 ) with an entity named a that was not declared.
Without using square brackets you could write for example
typedef int T[5];
T a = { 1, 2, 3, 4, 5 };
As for this your statement
Since *(a + 5) equals with a[5] , why i cannot initialize with:
then in this context *( a + 5 ) is not an array. It is an expression that yields an element a[5] provided that a was already declared as an array with the number of elements not less than 6. Otherwise a[5] will be a non-existent element of the array a.

You may try like this:
int *arr=(int*)malloc(5*sizeof(int));
for(int i=0;i<5;i++) {
scanf("%d",&(*(arr+i)));
}
or
int *arr=(int*)malloc(5*sizeof(int));
*(arr+0)=1;
*(arr+1)=2;
*(arr+2)=3;
*(arr+3)=4;
*(arr+4)=5;

Related

Is the use of (arr+2)[0] right?

I am a student who will be a freshman in an university after this summer vacation.I want to learn about computer programing in advance but I run into some problems.
Why when I run the program in devc++,the result is -1 and 44?
When I read the book called Pointers On C,In the chapter on functions,the book says that the name of array is a pointer,and in C language arr[m]=*(arr+m),and arr[0] is composed by a pointer and a [number],so can I come to a conclusion that (arr+2),which is a pointer,and[0],can compose (arr+2)[0] equaling to *(arr+2+0)?
int main(void)
{
int arr[10];
for(int i=0;i<10;i++)
{
arr[i]=i+1;
}
int b=*(arr+1);
int c=(arr+2)[0];//Is this true?
printf("%d\n",b);
printf("%d",c);
return 0;
}
Is the use of (arr+2)[0] right?
Linguistically yes. But very questionable practice.
The beautiful invention of C is pointer arithmetic and that is exemplified by the definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).
So by definition (arr+2)[0] is the same as (*((arr+2)+(0))) and simplifies to *(arr+2) and arr[2] simplifies to the same thing.
Array subscripting in C is syntactic sugar on pointer arithmetic. The term 'syntatic sugar' is sometimes overused. But in this case it really is just syntactic sugar.
The example demonstrates a critically important fact about how C manages arrays. Pointer arithmetic works in units of the type (measured in bytes they occupy) and array subscripting the same. So adding to a pointer (arr+2) and subscripting into an array (arr[2]) have a fundamental relationship.
When you understand that and realise the that array subscripts start at 0 because of that because they're offsets you get "C" as a language.
Please never write code like that. Writing code like 7[A] gets funny looks.
There is a typo in your code
for(int i=0;i<10;i++)
{
arr[0]=i+1;
}
It seems you mean
for(int i=0;i<10;i++)
{
arr[i]=i+1;
}
From the C Standard (6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).
So the expression
(arr+2)[0]
evaluates like
*( ( arr + 2 ) + 0 )
That is the same as
*( arr + 2 )
and in turn is the same as
arr[2]
You even may write
2[arr]
Pay attention to that the expression
(arr+2)[0]
will be more clear if to introduce an intermediate pointer like
int *p = arr + 2;
and then to use the expression
p[0]
C allows you to do all sorts of clever things with arrays and pointers.
This is either a good thing (if you like writing clever code) or very frustrating (if later you have to maintain some of that clever code)
All of the following are equivalent:
(arr+2)[0]
arr[2]
2[arr]
*( ( arr + 2 ) + 0 )
*( arr + 2 )
While they are equivalent, that doesn't necessarily mean you should use them interchangeably - my general recommendation is to use array notation when accessing an array, and pointer arithmetic when indexing into any other structures. Decaying an array into a pointer is prone to errors!
In noting that you have defined your data structure as an array int arr[10]; my advice would be to access it as arr[2] - then everyone is clear what you are trying to do, both now and in teh future.
As an aside (and see profile for affiliation) MISRA C dedicates a whole chapter (8.11) to pointer type conversion, and another (8.18) to the pitfalls of arrays and pointers - a fair bit of guidance and a total of 17 Rules between them...
#include <stdio.h> // printf
int main(void)
{
int arr[10];
printf("fill and print the array\n");
for(int i=0;i<10;i++)
{
arr[i]=i+1;
printf("%d -th element of the array = arr[%d] = %d\n",i+1, i, arr[i]);
}
printf("pointer arithmetic in c \n");
int b=*(arr+1); // arr[m]=*(arr+m)
int c=(arr+2)[0];//(arr+2)[0] = *(arr+2+0)
int n = 0;
printf("%d -th element of the array = arr[%d] = %d\n",n+1, n , *(arr + n));
printf("%d -th element of the array = %d\n",2,b);
printf("%d -th element of the array = %d\n",3,c);
return 0;
}
compile
gcc t.c -Wall -Wextra
run
./a.out
result:
fill and print the array
1 -th element of the array = arr[0] = 1
2 -th element of the array = arr[1] = 2
3 -th element of the array = arr[2] = 3
4 -th element of the array = arr[3] = 4
5 -th element of the array = arr[4] = 5
6 -th element of the array = arr[5] = 6
7 -th element of the array = arr[6] = 7
8 -th element of the array = arr[7] = 8
9 -th element of the array = arr[8] = 9
10 -th element of the array = arr[9] = 10
pointer arithmetic in c
1 -th element of the array = arr[0] = 1
2 -th element of the array = 2
3 -th element of the array = 3
HTH

Weird pointer to array syntax

What is the logic motivating int (*arr)[5]; to declare arr as a pointer to an array of 5 elements, whereas int *arr[5] declares arr as an array of 5 pointers ? Especially given that * has low priority (unsure about this part since it isn't used as the dereferencing operator) ?
In both declarations and expressions, postfix operators like [] have higher precedence than unary operators like *, so a declaration like
T *a[N];
is parsed as
T *(a[N]);
Thus
a -- a is
a[N] -- an N-element array of
*a[N] -- pointer to
T *a[N]; -- T
If you want to declare a as a pointer to an array, then you need to explicitly group the * operator with a:
T (*a)[N];
Thus:
a -- a is
(*a) -- a pointer to
(*a)[N] -- an N-element array of
T (*a)[N]; -- T
As luck would have it, you're far more likely to be using an arrays of pointers than pointers to arrays, so it makes sense that the "simpler" form of declaration results in that type.
You've already stated the reason: * has lower precedence than [].
So
int *a[5];
is
int *(a[5]);
meaning that a is an array first, and what it's an array of is pointers.
To me, this is a fine result. I declare arrays of pointers all the time, and int a[5] is convenient syntax. Trying to type int (*a)[5] feels very strange, but that's okay, because I never declare pointers to arrays (because they're virtually never useful).
What is the logic motivating int (*arr)[5];
It depends on the context. For example if you have a two-dimensional array then you can use a pointer of such a type as an iterator.
Here is a demonstrative program
#include <stdio.h>
int main( void )
{
int a[2][5] =
{
{ 0, 1, 2, 3, 4 },
{ 5, 6, 7, 8, 9 }
};
for (int(*row)[5] = a; row != a + 2; ++row)
{
for (int *col = *row; col != *row + 5; ++col)
{
printf("%d ", *col);
}
putchar('\n');
}
return 0;
}
Or if you have a function that declares its parameter as a two-dimensional array as for example
void f( int a[][5], size_t n );
then the parameter implicitly is adjusted to pointer of the type int ( * )[5]
Take into account that if you have an array like this
int * a[5];
then a pointer to the array will look
int * ( *p )[5] = &a;
While if you have an array like this
int a[5];
then a pointer to the array will look like
int ( *p )[5] = &a;

Are arrays just the same as constant pointers or are there any another differences? [duplicate]

This question already has answers here:
C: differences between char pointer and array [duplicate]
(14 answers)
Closed 7 years ago.
I've read various articles and questions here on SO about pointers and arrays equivalency. Nearly each article explains it different. I know that arrays and pointers are strongly related and bellow are my experiments with pointers and arrays equivalency, including comments which explain given behavior (feel free to correct me if I'm wrong somewhere). My question is: are arrays are just constant pointers or is there also another differences?
#include <stdio.h>
int main ()
{
// declaring array this way in fact declares a pointer with name "a" which points to the first element in the array:
int a[] = {0,1,2,3,4};
// assigning an array to the pointer in fact assigns the address of the first array element to the pointer, those two are thus equivalents:
int *pa1 = a;
int *pa2 = &a[0];
printf("########################\n");
// REFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%p\n", (a+0)); // a+0 == 0+a
printf("%p\n", a);
printf("%p\n", &a[0]);
printf("%p\n", &0[a]); // a+0 == 0+a
printf("########################\n");
// DEREFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%d\n", *(a+0)); // a+0 == 0+a
printf("%d\n", *a);
printf("%d\n", a[0]);
printf("%d\n", 0[a]); // a+0 == 0+a
printf("########################\n");
// REFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%p\n", (a+1));
printf("%p\n", &a[1]);
// REFERENCING: pointers can use array syntax (following are equivalents)
printf("%p\n", (pa1+1));
printf("%p\n", &pa1[1]);
printf("########################\n");
// DEREFERENCING: assigning values via pointers using pointer/array syntax (following are equivalents)
*(pa1+1) = *(pa1+1) + 10;
pa2[1] = pa2[1] + 10;
// DEREFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%d\n", *(a+1));
printf("%d\n", a[1]);
printf("%d\n", 1[a]);
// DEREFERENCING: assigning values via arrays using pointer/array syntax (following are equivalents)
*(a+2) = *(a+2) + 10;
a[2] = a[2] + 10;
// DEREFERENCING: pointers can use array syntax (following are equivalents)
printf("%d\n", *(pa1+2));
printf("%d\n", pa1[2]);
printf("%d\n", 2[pa1]);
printf("########################\n");
// REFERENCING: those two pointers points to the same address
printf("%p\n", pa1);
printf("%p\n", pa2);
// DEREFERENCING: those two pointers points to the same address
printf("%d\n", *pa1);
printf("%d\n", *pa2);
printf("########################\n");
// This is correct:
pa1++;
printf("%p\n", pa1);
printf("%d\n", *pa1);
printf("%p\n", pa2);
printf("%d\n", *pa2);
printf("########################\n");
return 0;
}
I would say that arrays are just constant pointers, the only thing that misleads me is that the error messages are different when I try to increment array and constant pointer, here is what I mean:
#include <stdio.h>
int main (){
int var1=0;
int * const ptr;
int a[] = {0,1,2,3,4,5};
// This gives an error:
// error: increment of read-only variable ‘ptr’
ptr++;
// This gives an error:
// error: lvalue required as increment operand
a++;
return 0;
}
If they are not the same can you please post some scenario where this difference is obvious?
Arrays and pointers are completely different animals.
Under most circumstances, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", but the array object itself is not a pointer.
This behavior has its roots in the B language, from which C was derived. In B, an array object was a pointer, and the subscript operation a[i] was interpreted as *(a + i) (offset i elements from address stored in a, dereference the result).
Ritchie kept the *(a + i) semantics, but got rid of the explicit pointer; C converts the array expression to a pointer expression instead (except when the array expression is the operand of the unary & or sizeof operators).
You may pretend, that arrays are the same as constant pointers, but in fact they are different types. One notable difference is a result of the sizeof operator. For instance:
#include <stdio.h>
int main(void)
{
int a[] = {0, 1, 2, 3, 4, 5};
int * const p = a;
printf("sizeof(a) = %zu\n", sizeof(a));
printf("sizeof(p) = %zu\n", sizeof(p));
}
For the former, you are getting total size of array. Assuming that sizeof(int) = 4, it prints 24. OTOH, for the latter, you just get the same as size of int pointer.
Also, you cannot use array initializer for pointer variable:
int * const p = {0, 1, 2, 3, 4, 5};
results into compiler's error if you set it with -pedantic-errors flag, e.g.:
error: excess elements in scalar initializer
Another important difference is that arrays are copied for each element during a struct assignment:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct threeNumbers {
int t[3];
} a = {{1, 2, 3}}, b = {{4, 5, 6}};
int main(void)
{
a = b;
a.t[0] = 100;
printf("%d\n", a.t[0]); // prints 100
printf("%d\n", b.t[0]); // prints 4
}
This is not the case for pointers. Structures with const pointers cannot be assigned to each other. For non-const pointers members, only an adress is copied. If pointers were set with malloc, then this might result into memory leak.

What is the difference between (int*) arr[2] and int* arr[2]?

Does (int*) arr[2] have to with typecasting? If yes, where is it used?
This problem arose when I tried to compile the follwing code :
int* arr[2];
int arr1[] = { 1,2};
int arr2[] = { 1,6};
arr[0] = arr1;
arr[1] = arr2;
by replacing
int* arr[2] with (int*)arr[2]
Thanks.
First one makes arr as an array of pointers to int. So your arr is a variable. That is a declaration line.
The second one: assuming that arr is a an array (which was allready declared!), takes the value which is arr[2] and casts a pointer to int type on it.
The problem with replacing int *arr[2] with (int *) arr[2] in your context is that the latter no longer conforms to the C grammar for declarations. According to the structure of C grammar, in int *arr[2] the * is attached to arr, not to int. Forcing it towards int by using extra () violates the suffix of a declaration.
You are allowed to use () in C declarations as long as it doesn't violate the syntactic structure of a declaration imposed by C grammar. For example, you can do
int *(arr)[2]; // same as `int *arr[2]`
or
int *(arr[2]); // same as `int *arr[2]`
or
int (*arr)[2]; // different from `int *arr[2]`, but still valid
but not your (int *) arr[2] or (int) *arr[2]. The latter are not declarations.

Why does this C array reference look incorrect?

Below is a piece of code copied from a website.
The value set for the direction prints the respective character from "nsew". For example the output of this code is character w.
I am wondering how does it work.
#include<stdio.h>
void main (void){
int direction = 3;
char direction_name = direction["nsew"];
printf("%c",direction_name);
}
This is because the array subscript operator is commutative, i.e., this:
const char *p = "Hello";
char x = p[0];
Is equivalent to
const char *p = "Hello";
char x = 0[p];
Weird, huh? In your case you are indexing into the third position of the string literal (which is an array) "nsew".
some_ptr[n] is equivalent to *(some_ptr + n), and since addition is commutative, it is also equivalent to *(n + some_ptr). It then follows that n[some_ptr] is also an equivalent expression.
I wouldn't recommend using this "feature" however... seriously, don't do it.
Operator [] has the same semantics as pointer arithmetics. So a[i] is equivalent to *(a + i) which is equivalent to *(i + a) which is equivalent to i[a]:
So direction["nsew"] == "nsew"[direction] == "nsew"[3] == 'w'

Resources