The Development of the C Language*
https://www.bell-labs.com/usr/dmr/www/chist.html
It is interesting that one of the key design aspects of the language was representation of pointers and by extension arrays.
Array - a collective name given to a group of similar quantities
C Arrays are a contiguous block of logical memory addresses that can be accessed using the same variable name
C Arrays are homogeneous
double height[10];
float width[20];
int c[9];
char name[20];
a[n]
is accessing (n+1) element of a
Arrays may be initialized to avoid starting with unknown values using {
first,
second ,
etc }
;
Uninitialized arrays are still accessible - might access garbage contents
If array size is not specified, the length of the initialization value array is used
int a[] = {10,20,30,40};
int a[4] = {10,20,30,40};
If specified array size > values initialized, all others initialized to zero
int a[5]={10,20,30};
//remaining values are initialized to 0Notable shorthand for initializing all elements to 0
Array assignment is not valid outside initialization
int a[4]; a = {10,20,30,40};
Arrays that live in statically-allocated memory are initialized to 0 since statically allocated memory is zeroed
#include "stdio.h" int x[3]; void main(){ int y[3]; for (int i=0;i<3;i++){ printf("x[%d]:%d\n",i,x[i]); } for (int i=0;i<3;i++){ printf("y[%d]:%d\n",i,y[i]); } }
x[0]:0 x[1]:0 x[2]:0 y[0]:21990 y[1]:1673393008 y[2]:32765
Here are multiple runs:
x[0]:0
x[1]:0
x[2]:0
y[0]:21975
y[1]:-187125696
y[2]:32764
x[0]:0
x[1]:0
x[2]:0
y[0]:21886
y[1]:714301776
y[2]:32767
For the adventurous, you can mix array/non-array initialized/not-initialled:
int a[]={1,2}, i,k=0;
[
index]
operator
c[0] = 3;
c[3] += 5;
y = c[x+1] ;
int arr[]={10,20,30,40}; int c=1,d=2,x,y; x=arr[c+d]; ++arr[c+d]; y=arr[c+d]; printf("x=arr[c+d] : %d\n",x); printf("y=++arr[c+d] : %d\n",y);
x=arr[c+d] : 40 y=++arr[c+d] : 41
x=arr[c+d] : 40
y=++arr[c+d] : 41
dangerous and undefined results accessing memory contents outside of the array
int x=100; int y=200; int A[]={10,20,30,40}; int B[]={50,60,70,80}; int u=300; int v=400; printf("A:\n"); for (int i=-4;i<10;i++) printf("%4d: %d\n",i,++A[i]); printf("x:%d\n",x); printf("y:%d\n",y); printf("u:%d\n",u); printf("v:%d\n",v);
A: -4: 51 -3: 61 -2: 71 -1: 81 0: 11 1: 21 2: 31 3: 41 4: 1 5: 1 6: -2020208511 7: 401 8: 301 9: 201 x:100 y:201 u:301 v:401
A:
-4: 51
-3: 61
-2: 71
-1: 81
0: 11
1: 21
2: 31
3: 41
4: 1
5: 1
6: -1760518015
7: 401
8: 301
9: 201
x:100
y:201
u:301
v:401
stack smashing protection
to run this example I had to disable GCC stack smashing protection
-fno-stack-protector
otherwise the following resulted
*** stack smashing detected ***: terminated
Aborted (core dumped)
Character arrays can be initialized using “string literals”
'\0'
– null characterEquivalent char arrays example:
char string1[] = "first";
char string1[] = {'f', 'i', 'r', 's', 't', '\0'};
Can access individual characters
if (string1[3] == 's') print("understood\n");
Length of string literal is the number of explicit characters+1
char string[5] = "first";
char string[10] = "first";
char string[10] = {'f', 'i', 'r', 's', 't', '\0', '\0', '\0', '\0', '\0'};
No simple syntax for non-initial string assignment
char string[10]; string="hello";will result in a syntax error
Intialzation Example
char string[10] = "first"; printf("string:\n"); for (int i=0;i<10;i++) printf(" %d: 0x%8x %c\n",i,string[i],string[i]);
string: 0: 0x 66 f 1: 0x 69 i 2: 0x 72 r 3: 0x 73 s 4: 0x 74 t 5: 0x 0 6: 0x 0 7: 0x 0 8: 0x 0 9: 0x 0
string:
0: 0x 66 f
1: 0x 69 i
2: 0x 72 r
3: 0x 73 s
4: 0x 74 t
5: 0x 0
6: 0x 0
7: 0x 0
8: 0x 0
9: 0x 0
scanf("%s", string1);
%s
Reads characters from stdin until whitespace encountered
in general avoid scanf() with %s -- it is dangerous
use of scanf
and %s
is sufficient at first for learning C, but safer alternatives that avoid buffer-overruns will be explained in a later lecture
#include <stdio.h> int main(){ char string1[11]="^^^^^^^^^^", string2[]="string"; int i; printf("Enter a string: "); scanf("%s", string1); printf("string1 is: %s\nstring2 is: %s\n", string1, string2); for(i=0;string1[i]!='\0';i++) printf("%c",string1[i]); printf("$\n"); for(i=0;i<11;i++) printf("[%2d] 0x%2x, %c\n",i,string1[i],string1[i]); printf("\n"); return 0; }
• include for printf/scanf • prompt • getting input using scanf • printing strings using printf • printing by iteration through char array
Enter a string: Hello there
string1 is: Hello
string2 is: string
Hello$
[ 0] 0x48, H
[ 1] 0x65, e
[ 2] 0x6c, l
[ 3] 0x6c, l
[ 4] 0x6f, o
[ 5] 0x 0,
[ 6] 0x5e, ^
[ 7] 0x5e, ^
[ 8] 0x5e, ^
[ 9] 0x5e, ^
[10] 0x 0,
•NULL-termination from scanf •NULL-termination from intialization
int a[3][2] = {{1},{3,4}};
Result shown in table
0 | 1 | |
---|---|---|
0 | 1 | 0 |
1 | 3 | 4 |
void ChangeElement(int array[ ], int index, int value);
void ChangeElement(int array[
300], int index, int value);
myFunction(myArrayName);
#include <stdio.h> void ChangeElement(int array[ ], int index, int value){ array[index]=value; } void main(){ int arr [ ]={10,20}; ChangeElement(arr,0,99); //a becomes 99,20 for(int i=0;i<2;i++) printf("[%2d]: %2d\n",i,arr[i]); }
[ 0]: 99 [ 1]: 20
[ 0]: 99
[ 1]: 20
#include <stdio.h> void ChangeElement(int array[ ], int index, int value){ array[index]=value; } void main(){ const int arr [ ]={10,20}; ChangeElement(arr,0,99); //a becomes 99,20 for(int i=0;i<2;i++) printf("[%2d]: %2d\n",i,arr[i]); }
/tank/robucci/GIT/cmpe311/Lectures/CBasics/9qyqvrxn0_code_chunk: In function ‘main’: /tank/robucci/GIT/cmpe311/Lectures/CBasics/9qyqvrxn0_code_chunk:8:19: warning: passing argument 1 of ‘ChangeElement’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 8 | ChangeElement(arr,0,99); //a becomes 99,20 | ^~~ /tank/robucci/GIT/cmpe311/Lectures/CBasics/9qyqvrxn0_code_chunk:2:24: note: expected ‘int *’ but argument is of type ‘const int *’ 2 | void ChangeElement(int array[ ], int index, int value){ | ~~~~^~~~~~~~ [ 0]: 99 [ 1]: 20
code_chunk.c: In function ‘main’:
code_chunk.c:8:19: warning: passing argument 1 of ‘ChangeElement’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
8 | ChangeElement(arr,0,99); //a becomes 99,20
| ^~~
code_chunk.c:2:24: note: expected ‘int *’ but argument is of type ‘const int *’
2 | void ChangeElement(int array[ ], int index, int value){
| ~~~~^~~~~~~~
Warning is based on the argument passing, not the actual operations in the code.
In the following function, the array is not modified yet the same warning is generated
#include <stdio.h> int ReadElement(int array[ ], int index){ return array[index]; } void main(){ const int arr [ ]={10,20}; printf("arr[0]: %d",ReadElement(arr,0)); }
/tank/robucci/GIT/cmpe311/Lectures/CBasics/ycjdjwqas_code_chunk: In function ‘main’: /tank/robucci/GIT/cmpe311/Lectures/CBasics/ycjdjwqas_code_chunk:8:37: warning: passing argument 1 of ‘ReadElement’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 8 | printf("arr[0]: %d",ReadElement(arr,0)); | ^~~ /tank/robucci/GIT/cmpe311/Lectures/CBasics/ycjdjwqas_code_chunk:2:21: note: expected ‘int *’ but argument is of type ‘const int *’ 2 | int ReadElement(int array[ ], int index){ | ~~~~^~~~~~~~ [ 0]: 99 [ 1]: 20
code_chunk.c: In function ‘main’:
code_chunk.c:8:31: warning: passing argument 1 of ReadElement discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
8 | printf("%d",ReadElement(arr,0));
| ^~~
code_chunk.c:2:23: note: expected ‘int *’ but argument is of type ‘const int *’
2 | int ReadElement(int array[ ], int index){
| ~~~~^~~~~~~~
arr[0]: 10
int AccessElement(const int a[], int index);
#include <stdio.h> int ReadElement(const int array[ ], int index){ return array[index]; } void main(){ const int arr [ ]={10,20}; printf("arr[0]: %d",ReadElement(arr,0)); }
[ 0]: 99 [ 1]: 20
arr[0]: 10