2

This is my file1 called main.c

#include <stdio.h>
#include <stdlib.h>

#define MONTHS 12
void ChangeDay(void);
int* days;

int main(void)
{
    days = (int*) malloc(MONTHS * sizeof(int));
    if(days != NULL)    
        ChangeDay();    
    else    
        return 1;   
    printf("%2d.\n", days[0]);
    return 0;
}

The global variable days is declared as a pointer to type int, and malloc is used to allocate space for 12 integers.

This is my file 2 called day.c

int days[];
void ChangeDay(void)
{
    days[0] = 31;
}

When the function ChangeDay is called, decimal value 31 is assigned to the first element of the array days .

This is code output :

root@where:~gcc -m32 -Wall -o day main.c day.c
day.c:1: warning: array ‘days’ assumed to have one element
root@where:~./day Segmentation fault

I will be grateful if you explain me this results .

My questions :

  • What is the right way to declare the variables( including arrays ) across multiple source files ?
  • How to access an element of a array using pointer, when they are declared in different files ?
boleto
  • 1,149
  • 1
  • 22
  • 32

3 Answers3

5

Every declaration of an identifier for an object must have compatible type with the other declarations. int *days and int days[] are different types. The former is a pointer to an int. The latter is an array of int.

In the first file, use:

int *days;

In the second file, use:

extern int *days;

Additionally: int *days; is a tentative definition of days. When the compiler reaches the end of the translation unit (the source file being compiled), it changes the tentative definition into a definition of the object (with a zero initializer). extern int *days; is a declaration of days that is not a definition. It tells the compiler that days is a name for an object that exists somewhere else.

You should have only one definition for each object. Other files that refer to the object should only declare the name and not define the object.

Sometimes there is confusion about a declaration such as int days[] because using this in a function parameter declares the parameter to be of type int *. This is a special adjustment that happens only in function parameters and not in other declarations.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Eric but this is not segmentation - fault reason I think! – Grijesh Chauhan Jul 24 '13 at 19:41
  • @GrijeshChauhan: I tested the original code and my code. My change fixes the problem. – Eric Postpischil Jul 24 '13 at 19:42
  • because its correct fix even I was about to answer this, but check my answer, I given a link of codepade view that too. – Grijesh Chauhan Jul 24 '13 at 19:44
  • I just wanted to share with you, Is it not surprising to see that code executing whereas if you use proper flags as I suggested you get a compilation time error!! Similarly I wounder why OP code could compile -because probably its a bug in compiler – Grijesh Chauhan Jul 24 '13 at 19:50
  • @GrijeshChauhan: I compiled, as I habitually do, with GCC flags “-Wmost -pedantic -std=c99”. There is no compilation error here. Can you cite the section of the C standard that this purportedly violates? – Eric Postpischil Jul 24 '13 at 19:57
  • actually my discussion with your is my confusion. I written this code by chance when I was writing [a answer here](http://stackoverflow.com/questions/17790127/what-is-meant-by-char-temp3/17790207#17790207). I didn't get any link to read about this but I checked that if I compile my code without `-pedantic -error` it compiles and executes while if I use flag its an error! It was/ and its quit surprising to me! – Grijesh Chauhan Jul 24 '13 at 20:03
  • btw your answer is good, and Thanks to guide and help me! If you find something related to this let me know. – Grijesh Chauhan Jul 24 '13 at 20:16
1

Reason for segmentation fault:

int days[]; // is errror 
void ChangeDay(void)
{
    days[0] = 31;
}

declaration this is error int days[];, you don't give it size and initialized it. So you can't use day[0] = 31; -- this is illegal and causes segmentation fault.

To get an error instead of warning compile your code like:

gcc -pedantic -error then only it will give you an error.

else this code will not give you an error, Its confusing but check this code its working Codepade. and this code will give you an error if you compile it proper flags as I suggested.

Additionally, as you wants to share same day[] array declare it as suggested by @Eric Postpischil

I am not deleting my answer presently as I want other users to view the linked code @ codepade and tell me whether it should be compile with new compilers? or its a bug in compiler?

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • 3
    A declaration of `int days[];` is not a problem by itself. It declares `days` with an incomplete type. You may **define** `days` in one file with `int days[3];`, for example, and **declare** it in another file with `extern int days[];`. However, since the question shows `days` being assigned memory with `malloc`, either it should be a pointer and not an array or it should be an array and the `malloc` should be deleted. – Eric Postpischil Jul 24 '13 at 19:48
  • @EricPostpischil No `int days[];` correct as function argument but as formal declaration its error according to C standard. – Grijesh Chauhan Jul 24 '13 at 19:51
  • I am sorry, I do not understand that sentence. Are you saying that a declaration such as `void foo(int days[]);` is not legal? It is legal. It is adjusted to `void foo(int *days);` per C 2011 (N1570) 6.7.6.3 7. If you are saying it is not legal at file scope, that is also incorrect; `int days[];` is a legal declaration. – Eric Postpischil Jul 24 '13 at 19:54
  • @EricPostpischil ok Which compiler you have try the code I linked or OP code with flag I suggested or without that. – Grijesh Chauhan Jul 24 '13 at 19:55
  • @EricPostpischil No `void foo(int days[]);` is valid, But what declaration OP given in his code and what I have given in my linked code it wrong. It could compile because its buggy compiler. – Grijesh Chauhan Jul 24 '13 at 19:59
  • @EricPostpischil hi! Are your there? [Read-Comment](http://stackoverflow.com/questions/12437648/uninterruptable-process-in-windowsor-linux?noredirect=1#comment26048209_12437648) by Daniel Fischer. Its compiler extension. – Grijesh Chauhan Jul 24 '13 at 20:37
  • 1
    @GrijeshChauhan Thanks for help, I tried with _GCC version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1)_, and code compiles fine with flag `-pedantic -error`. – boleto Jul 24 '13 at 21:17
  • @GrijeshChauhan warning and error are the same as in my question. – boleto Jul 24 '13 at 21:24
  • @boleto Ok, So instead of warning you got an error under Ubuntu with gcc4.4.3 **?** Correct ? – Grijesh Chauhan Jul 24 '13 at 21:26
  • @boleto wait compile it as: `gcc -pedantic-errors -Wall std=c99 souce.c -o exename`. – Grijesh Chauhan Jul 24 '13 at 21:50
  • @GrijeshChauhan Tested with three versions of GCC in to different platforms: 4.7.1 (tdm-1) win32; 4.5.3 i686-pc-cygwin; 4.4.3 x86_64-linux-gnu; The options are the same: `gcc -pedantic-errors -Wall -std=c99 -o test main.c day.c` The code compiles without error. Warnings is : *day.c:1: warning: array ‘days’ assumed to have one element* – boleto Jul 30 '13 at 02:52
  • @boleto :( quite confusing results. but thing is it an error excepting gcc compilers.--Thanks Boleto! – Grijesh Chauhan Jul 30 '13 at 06:13
0

You have to declare the array in one c file, and declare the variable as extern in the other c file.

KrisSodroski
  • 2,796
  • 3
  • 24
  • 39
  • Yes, the array must be defined (not just declared) in one file and declared (not defined) with `extern` in another. However, the types must also be compatible. `int *` and `int []` are incompatible. This answer will not solve the problem. – Eric Postpischil Jul 24 '13 at 19:43