linking problem when calling main.c in compilation unit - c

Suppose that we call main.c in another c file in the compilation unit.
I understand that this is illegal since we can only call header file. However, why does it cause a bad linking but not a bad compiling when we make build everything?
The C file that calls main should be something like this:
#include "main.c"
int add (int x, int y) { return x+y; }
}

It is generally a bad idea to #include C files, but there is nothing strictly illegal about it. The #include directive effectively copies the source code directly into the current file. What you currently have can be made to work:
$ cat main.c
#include <stdlib.h>
#include <stdio.h>
int add(int, int);
int
main(int argc, char **argv)
{
int a = argc > 1 ? strtol(argv[1], NULL, 10) : 1;
int b = argc > 2 ? strtol(argv[2], NULL, 10) : 1;
printf("%d + %d = %d\n", a, b, add(a, b));
return 0;
}
$ cat add.c
#include "main.c"
int add(int x, int y) { return x + y; }
$ cc add.c
$ ./a.out
1 + 1 = 2
$ ./a.out 3 -5
3 + -5 = -2
If you are getting linkage problems, it is probably because you are trying to do something like:
$ cc main.c add.c
Which is problematic since you now have duplicate definitions of main
Possibly what you want to do is to remove the #include from the add.c and do something like:
$ cat add1.c
int add(int x, int y) { return x + y; }
$ cc -c add1.c
$ cc main.c add1.o

Related

gprof only showing calls - C program in Ubuntu with WSL1

I am having an issue with "gprof" while using WSL1 and "gcc" in Ubuntu. The only information it displays is the "calls" and anything else is set as 0.00. I do not think that is because the program is running too fast because when typing time ./go it returns:
real = 0.569s; user = 0.547s; sys = 0.000s.
The main program (go.c) is:
#include <stdio.h>
#include "functions.h"
#define maxloop 1e7
int main(int argc, char*argv[]) {
int i;
double x;
double xsum = 0.0;
for (i = 1; i < maxloop; i++) {
x = myFun1(i) + myFun2(i) + myFun3(i);
xsum += x;
}
printf("xsum = %.6f\n", xsum);
return 0;
}
The file with the functions (functions.c) is:
#include <math.h>
double myFun1(double x) {
double a = sin(x);
return a;
}
double myFun2(double x){
double a = pow(x,3);
return a;
}
double myFun3(double x){
double a = sqrt(x);
return a;
}
The header (functions.h) is:
double myFun1(double x);
double myFun2(double x);
double myFun3(double x);
I am compiling in the terminal as:
gcc -pg -o go go.c functions.c -lm
Running the gprof as:
gprof ./go -p -b
Upgrade to WSL2 for support of the profiling features required by gprof.

How to fix warning occured during compiling of C program on fedora

I am trying to learn how to split a c program in more than one file but during compilation it throws warning as given below:
$ gcc ./p1.c ./p2.c -o ./p1
./p2.c:2:1: warning: data definition has no type or storage class
2 | b = 6;
| ^
./p2.c:2:1: warning: type defaults to ‘int’ in declaration of ‘b’ [-Wimplicit-int]
where,
p1.c
#include <stdio.h>
#include "p2.h"
int a = 5;
int main(void) {
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", square(b));
return 0;
}
p2.c
#include "./p2.h"
b = 6;
int square(int x) {
return x * x;
}
and p2.h
#ifndef P2_H
#define P2_H
extern int b;
int square(int);
#endif
all of these files are present in same directory but i am still getting the warning, after trying several searching on the internet i can't find how to fix it.
Thank You In Advance.
p2.c should have a normal definition of the global variable:
#include "./p2.h"
int b = 6;
int square(int x) {
return x * x;
}

How to link main with made libraries?

I'm trying to link libraries I made to main source code, but it throws this error. I've been searching for last two hours how to fix this but nothing worked for me.
Compiling:
cd "c:\Users\miros\OneDrive\Documents\C codes\labovi"
gcc 01main.c -o 01main
.\01main
d:/programs/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\miros\AppData\Local\Temp\ccGHtHKg.o:01main.c:(.text+0x46): undefined reference to 'faktorijel'
d:/programs/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\miros\AppData\Local\Temp\ccGHtHKg.o:01main.c:(.text+0x72): undefined reference to 'suma'
collect2.exe: error: ld returned 1 exit status
01ucitavanje.h
#ifndef UCITAVANJE_H
#define UCITAVANJE_H
#include <stdio.h>
#include <stdlib.h>
long long *niz;
int n;
void ucitavanje();
#endif
01ucitavanje.c
#include "01ucitavanje.h"
void ucitavanje(){
scanf("%d", &n);
niz = malloc(sizeof(long long) * n);
for (int i = 0; i < n; i++)
scanf("%d", niz + i);
}
01izracunavanje.h
#ifndef IZRACUNAVANJE_H
#define IZRACUNAVANJE_H
#include <stdio.h>
long long faktorijel(int n);
long long suma(long long *niz, int n);
#endif
01izracunavanje.c
#include "01izracunavanje.h"
long long faktorijel(int n){
long long f;
for (int i = 2; i <= n; i++)
f *= i;
return f;
}
long long suma (long long *niz, int n){
long long s = niz[0];
for (int i = 1; i < n; i++)
s += niz[i];
return s;
}
main.c
#include "01izracunavanje.h"
#include "01ucitavanje.h"
int main(){
ucitavanje();
for (int i = 0; i < n; i++)
niz[i] = faktorijel((int)niz[i]);
printf("%d", suma(niz, n));
free(niz);
return 0;
}
You're compiling only main.c into the executable, so the other functions aren't available.
You need to compile each source file into an object file, then link the object files together.
gcc -c main.c
gcc -c 01izracunavanje.c
gcc -c 01ucitavanje.c
gcc -o 01main main.o 01izracunavanje.o 01ucitavanje.o
I'm going to give you a mid-line correction because you put your compilation on one very long line.
In this case, you pass all your .c files to gcc. From
{ gcc 01main.c -o 01main }
We'd rather write
{ gcc -o 01main 01main.c 01izracunavanje.c 01ucitavanje.c }
Since you're not actually building a distribution library but rather a bunch of source files we just compile them all together. It generates better code that way anyway once you start optimizing.
Order of .c files doesn't really matter, but the file containing main is first by tradition. Putting -o before the first .c file used to matter and most people still do it.

multifile direct compile ok, direct compile error

There are 3 files(generator.c, generator.h and main.c).
generator.c: There is only 1 function (gen fun) which is used to generate an array to store 10 random-generate numbers in generator.c.
generator.h:Declaration of generator.c.
main.c: There is only 1 function (main fun) in main.c which is used to print the number generated previously.
If generator.c is included in main.c and I compile it directly by execute "gcc main.c". The result is ok.
But while I compile it using " gcc -c generator.h, gcc -c main.c, gcc generator.o main.o ", it reported a warning "warning: assignment makes pointer from integer without a cast" at " p = gen(arr); " sentence in main funciton. And the final result was "Segmentation fault (core dumped)". The debug information showed "Cannot access memory at address" if i try to visit the value of pointer *p(i.e. array[0]) in the while loop of main function.
//////generator.c///////
int * gen( int arr[])
{
int i = 0;
int * p = arr;
int len = 10;
srand( (unsigned)((time)(NULL)));
while (i< len)
{
*p = rand() % ( len +1) + 0;
i ++;
p++;
}
return arr;
}
//////generator.h//////
int * gen( int arr[]);
//////main.c///////
int main(void)
{
int i = 0;
int arr[10]={0};
int * p;
p = gen(arr);
while (i < 10)
{
printf("output is %d\n",*p);// Segmentation fault (core dumped)
i++;
p++;
}
return 0;
}
Based on the addition to your question, it appears you are confused about how to include generator.h and then to compile the code. First your generator.h should be:
//////generator.h//////
#ifndef GENERATOR_H
#define GENERATOR_H 1
int *gen (int arr[]);
#endif
(edit: added appropriate Header Guards to prevent multiple inclusion of generator.h)
Your generator.c would then be:
//////generator.c///////
#include <stdlib.h>
#include "generator.h"
int *gen (int arr[])
{
int i = 0;
int * p = arr;
int len = 10;
while (i< len)
{
*p = rand() % len + 1;
i ++;
p++;
}
return arr;
}
And finally your main.c (I called it gen.c) would be:
//////main.c///////
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "generator.h"
int main(void)
{
int i = 0;
int arr[10]={0};
int *p;
srand( (unsigned)((time)(NULL)));
p = gen(arr);
while (i < 10)
{
printf ("output is %d\n",*p);
i++;
p++;
}
return 0;
}
Compile
$ gcc -Wall -Wextra -pedantic -std=c11 -Ofast generator.c -o bin/gen gen.c
(note: I would also encourage adding -Wshadow as a normal part of your compile string as well to identify any shadowed variables)
Example Use/Output
$ ./bin/gen
output is 8
output is 1
output is 5
output is 4
output is 9
output is 5
output is 4
output is 6
output is 5
output is 6
Look things over and let me know if you have further questions.

Fail to link c code to lapack / blas : undefined reference

i have been trying for hours and it drives me crazy. The last error I get is :
demo_cblas.c:(.text+0x83): undefined reference to `clapack_sgetrf'
demo_cblas.c:(.text+0xa3): undefined reference to `clapack_sgetri'
I am compiling the code using
/usr/bin/gcc -o demo_cblas demo_cblas.c -L /usr/lib64 -l :libgfortran.so.3 -L /usr/lib64 \
-llapack -L /usr/lib64 -lblas
I try with and without libgfortran, with different compilers gcc-33, gcc-47, gcc-48. The test code is not from me but comes from this forum ...
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "clapack.h"
#include "cblas.h"
void invertMatrix(float *a, unsigned int height){
int info, ipiv[height];
info = clapack_sgetrf(CblasColMajor, height, height, a, height, ipiv);
info = clapack_sgetri(CblasColMajor, height, a, height, ipiv);
}
void displayMatrix(float *a, unsigned int height, unsigned int width)
{
int i, j;
for(i = 0; i < height; i++){
for(j = 0; j < width; j++)
{
printf("%1.3f ", a[height*j + i]);
}
printf("\n");
}
printf("\n");
}
int main(int argc, char *argv[])
{
int i;
float a[9], b[9], c[9];
srand(time(NULL));
for(i = 0; i < 9; i++)
{
a[i] = 1.0f*rand()/RAND_MAX;
b[i] = a[i];
}
displayMatrix(a, 3, 3);
return 0;
}
I am on Suse 12.3 64bits. In /usr/lib64 I have liblapack.a liblapack.so, ... and libblas.a libblas.so, ... and libgfortran.so.3
The same code without the function "invertMatrix" (the one using the library) compiles fine.
Any idea or suggestion ?
Thank you all for your help.
Vava
I'm quite positive that you also need to link to libcblas, which is the c wrapper library for libblas. Note that libblas is a FORTRAN library which therefore does not contain the function clapack_* you're calling.
I've just got this working on FreeBSD with:
gcc -o test test.c \
-llapack -lblas -lalapack -lcblas
I'd installed math/atlas (from ports) and the lapack and blas packages.
See my question here

Resources