I have these files..

str.h

#ifndef _str_h_
#define _str_h_

struct STRSTR
{
    char* MainStr;
    char* SubStr;
};

char* str_str(int, int, struct STRSTR* sample);
void init(char*, struct STRSTR* sample);


#endif /* _str_h_ */

str.c

#include "str.h"
#include <stdio.h>
void init(char* str, struct STRSTR* sample){
    sample->MainStr = str;
}


char* str_str(int index, int size, struct STRSTR* sample){
    int length = 0;
    while ( *(sample->MainStr + length)!= '\0' )
        length++;
    if (index > length)
        printf( "ERROR!! Index value is greater than the actual size" );
    else{
        char temp[length];
        int i;
        for ( i = index; i < size; i++ ) {
            temp[i] = *(sample->MainStr + i);
        }   
        temp[size] = '\0';
        sample->SubStr = temp;
    }
return sample->SubStr;
}

main.c

#include "str.h"
#include <stdio.h>
int main() {

    extern struct STRSTR sample;
    init((char*)"Hello World", &sample);
    char* out = str_str(0, 5, &sample);
    printf("%s", out);


return 0;
}

and my Makefile

MAIN = main
HEADER_DEFINITIONS = str.c
CC = gcc
COMPILE = -c
EXE = $(MAIN)
OPTIMIZE = -Os
SHELL = /bin/bash
NO_WARNINGS = -w
VERBOSE = -v

all: link
    @echo "Executing..........."
    @echo " > > > > > > OUTPUT < < < < < < "
    @$(SHELL) -c './$(EXE)'

link: compile
    @echo -n "Linking............."
    @$(SHELL) -c '$(CC) -o $(EXE) *.o'

compile: $(MAIN).c $(HEADER_DEFINITIONS)
    @echo -n "Compiling........."
    @$(SHELL) -c '$(CC) $(OPTIMIZE) $(COMPILE) $(NO_WARNINGS) $^'

clean:
    @echo "Cleaning............"
    @$(SHELL) -c 'rm -f *~ *.o $(EXE)'

This shows error like this

main.o: In function main': main.c:(.text.startup+0x2): undefined reference tosample'
main.c:(.text.startup+0x11): undefined reference to sample' collect2: error:ld returned 1 exit status`

Please help me..Thanks in advance..

Edited 1 Year Ago by Mayukh_1

Hello friends I solved it partially...When I remove the keyword extern it builds all right

But this brings me to my next question..Why with extern keyword it raised those liking errors..

I am still not marking it as solved.

The reason is simple: the variable sample is not external to the main.c file, and in fact is a local variable of the main() function itself. When you declared the variable as extern, you were telling the linker, "I want to access a variable defined in another object", which isn't what you were doing at all.

It should make sense once you understand what extern is meant for. My guess - because it is a common misunderstanding, and one I had made myself at one time - is that you expected the extern specifier to make the local variable visible to the other file, but this in in fact the opposite case.

The primary purpose of the extern specifier is to assert that a variable of that name can be found somewhere other than the file the extern declaration appears in - it is most often used in header files to allow a shared variable used by a linked library to be accessible by programs linking in said library. This allows the variable to be made visible via the header, but avoids the problem of redeclaration, because the actual declaration is in the library. So, if you have a shared variable foo in foo.c:

int foo = 42;

you would have it declared in the header, foo.h:

extern int foo;

which could be then #included by a program file, say main.c:

#include "foo.h"

int main()
{
    printf("Foo == %d", foo);
    return 0;
}

In any case, you aren't actually sharing the variable sample in either direction; rather, you are passing a reference to it as an argument to the two functions which work on it, so the variable itself doesn't actually need to be visible to str.c in the first place.

Edited 1 Year Ago by Schol-R-LEA

So you meant that we should declare a variable in a source file & later on if we need to sahre that variable to some other source file then we use the keyword extern in a header file and include the header file in the required source files?

This is pretty commendable because yes you are true that I knew it exactly opposite..

Generally speaking, you want to avoid sharing the variable directly at all; global variables are generally considered an anti-pattern, something to avoid unless there is no alternative.

When you need to access a variable in more than one function, you usually want to pass the variable (or a reference or pointer to it) as an argument to the called function instead. This makes the function more modular and easier to reuse, and helps avoid difficult-to-detect side effects. By parameterizing function rather than relying on implicit global state, it makes for a cleaner interface between the functions.

So in the above example, I passed the pointer to the structure objects to the global functions. I also thought about passing a pointer of the structure type & then access the variables using that pointer but then resot to this method..Which one you think is better..??

This article has been dead for over six months. Start a new discussion instead.