i am using makefiles in c, i have three files and each of the three have all the declarations of each variable. so it looks like this when i compile.
/usr/bin/ld: comp_disc.o:(.bss+0x8): multiple definition of `Cost_of_purchase'; main.o:(.bss+0x8): first defined here
/usr/bin/ld: comp_disc.o:(.bss+0x10): multiple definition of `DiscTot'; main.o:(.bss+0x10): first defined here
/usr/bin/ld: comp_disc.o:(.bss+0x18): multiple definition of `Sales_tax'; main.o:(.bss+0x18): first defined here
/usr/bin/ld: comp_disc.o:(.bss+0x20): multiple definition of `Total_price'; main.o:(.bss+0x20): first defined here
/usr/bin/ld: comp_disc.o:(.bss+0x28): multiple definition of `military'; main.o:(.bss+0x28): first defined here
but when i only keep those declarations on main.c i get this.
comp_disc.c:10:12: error: ‘Cost_of_purchase’ undeclared (first use in this function)
10 | if(Cost_of_purchase > 150) {
| ^~~~~~~~~~~~~~~~
comp_disc.c:11:13: error: ‘Mdisc’ undeclared (first use in this function)
11 | Mdisc = .15 * Cost_of_purchase;
so I'm wondering what i need to do so that my variables are declared correctly using make
here is my makefile
# target : dependencies
2 cwork7 : main.o comp_disc.o print_res.o
3 gcc main.o comp_disc.o print_res.o -Wall -o cwork7
4
5 main.o : main.c
6 gcc -c main.c -Wall
7
8 comp_disc : comp_disc.c
9 gcc -c comp_disc.c -Wall
10
11 print_res.o : print_res.c
12 gcc -c print_res.c -Wall
my main.c
5 #include <stdio.h>
6 //functions prototypes
7 void compute_discount(void);
8 int print_results(void);
9
10
11 //defined Gloabal var
12 double Mdisc;
13 double Cost_of_purchase;
14 double DiscTot;
15 double Sales_tax;
16 double Total_price;
17 char military;
18
19 int main (void) {
20 //declare variables
21
22 //Cost of purchase
23 printf("Cost of purchase?\t\t$");
24 scanf ("%lf",&Cost_of_purchase);
25
26 //Military?
27 printf("In military (y or n)?\t\t");
28 scanf(" %c" ,&military);
29
30 //calling for functions
31 compute_discount();
32 print_results();
33
34 }
35
36
my print_res.c
1 #include <stdio.h>
2
3 //function to print results
4 int print_results(void){
5
6 //if input is y Y then use below, this is not dependant on if military only if the letter is accepted
7 switch(military){
8 case 'y':
9 case 'Y':
10 printf("Military discount (15%%): \t$%.2f\n", Mdisc);
11 printf("Discounted total: \t\t$%.2f\n", DiscTot);
12 printf("Sales tax (5%%): \t\t$%.2f\n", Sales_tax);
13 printf("Total: \t\t\t\t$%.2f\n", Total_price);
14 break;
15 //less information is given when n or N is used
16 case 'n':
17 case 'N':
18 printf("Sales tax (5%%): \t\t$%.2f\n", Sales_tax);
19 printf("Total: \t\t\t\t$%.2f\n", Total_price);
20 break;
21 }
22 return(0);
23 }
and my comp_disc.c
1 #include <stdio.h>
2
3 //function to compute discount
4 void compute_discount(void){
5
6 //compute military discount
7 switch(military){
8 case 'y':
9 case 'Y':
10 if(Cost_of_purchase > 150) {
11 Mdisc = .15 * Cost_of_purchase;
12 } else if (Cost_of_purchase < 150) {
13 Mdisc = .10 * Cost_of_purchase;
14 }
15 break;
16 case 'n':
17 case 'N':
18 Mdisc = 0;
19 break;
20 default:
21 printf("Error: bad input\n");
22 }
23
24 //cost minus military discount
25 DiscTot = Cost_of_purchase - Mdisc;
26 //sales tax
27 Sales_tax = .05 * DiscTot;
28 //Total Calculated
29 Total_price = DiscTot + Sales_tax;
30
31 }
Please let me know what you think is the issue.
This has nothing to do with the Makefile.
If you define the variables in all source file you get exactly what the linker says, multiple definitions of the same name. And if you drop them from the file you obviously get a compile error as you are using variables the compiler does not know about.
The simple solution is to keep the variables in main as-is, but to define them as extern in all other files, like extern double Cost_of_purchase; That tells the compiler the variable exists, but is already defined elsewhere, which solves the problem.
However, just don't use global variables. Pass your data to the functions.
struct acc_data {
double Mdisc;
double Cost_of_purchase;
double DiscTot;
double Sales_tax;
double Total_price;
char military;
}
int main(void)
{
struct acc_data acc = { 0 };
// init code skipped
compute_discount(&acc);
print_results(&acc);
}
void compute_discount(struct acc_data *acc)
{
//same as before but prefix variables with acc->
// example:
acc->Total_price = 5000.0;
}
That gets rid of your original problem and improves your code somewhat.
Put the definition of the struct in a header file you include in all C files that use it.
Related
I am using Debian 11
I am trying to reproduce strlcpy.
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4
5 unsigned int ft_strlcpy(char *dest, char *src, unsigned int size)
6 {
7 unsigned int i;
8
9 i = 0;
10 while (src[i] && i < size)
11 {
12 dest[i] = src[i];
13 i++;
14 }
15 dest[i] = '\0';
16 while (src[i])
17 i++;
18 return (i);
19 }
20
21 int main()
22 {
23 unsigned int i;
24 char *dest1 = malloc(sizeof(char) * 50);
25 char *dest2 = malloc(sizeof(char) * 50);
26
27 i = 0;
28 while (i < 26)
29 {
30 printf("%d ", ft_strlcpy(dest1, "hello my name is marcel", i));
31 printf("%s\n", dest1);
32 printf("%ld ", strlcpy(dest2, "hello my name is marcel", i));
33 printf("%s\n", dest2);
34 i++;
35 }
36 free(dest1);
37 free(dest2);
38 return (0);
39 }
However, I get this message when I compile my code:
ft_strlcpy.c: In function ‘main’:
ft_strlcpy.c:32:18: warning: implicit declaration of function ‘strlcpy’; did you mean ‘strncpy’? [-Wimplicit-function-declaration]
32 | printf("%ld ", strlcpy(dest2, "hello my name is marcel", i));
| ^~~~~~~
| strncpy
/usr/bin/ld: /tmp/ccukR8g6.o: in function `main':
ft_strlcpy.c:(.text+0xf0): undefined reference to `strlcpy'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: ft_strlcpy] Error 1
I have no idea how to include libbsd or use pkgconf.
I have tried for a couple of hours, but I couldn't find the solution.
If someone could redirect me to a manual or explain the concepts, that would be great.
Thank you for your help!
The strlcpy function is included in the BSD libc, a superset (extended version) of the POSIX standard library for BSD operating systems. For it to be recognized by the compiler you have to first install the library through your package manager, the name of which will be either libbsd, libbsd-dev or libbsd-devel depending on whether your distribution uses seperate development libraries or not, and than include it as <bsd/string.h>. You can then compile it with (assuming you use GCC) gcc <your-filename>.c -lbsd, specifying the library to be linked. I wouldn't recommended using BSD functions outside of BSD specific software due to portability issues (POSIX incompliences).
I have the following program in Mingw, gcc 4.9.2:
#include <stdio.h>
#include <stdint.h>
#define VECSIZE 32
typedef char byteVec __attribute__ ((vector_size (VECSIZE)));
#define PERMLEFT_BVEC (byteVec){63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}
byteVec permute(byteVec x, byteVec y) {
return __builtin_shuffle(x,y,PERMLEFT_BVEC);
}
void print_vec32b(byteVec a) {
printf("[ ");
int i; for (i = 0; i < 32; ++i) printf("%d ", a[i]);
puts("]");
}
int main() {
byteVec x = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
byteVec y = {11,12,13,14,15,16,17,18,19,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,88,89,90,91,92};
byteVec z = permute(x,y);
print_vec32b(x);
return 0;
}
When I compile this program with -m64, it crashes. With -m32 it works fine. Optimization level doesn't matter. I don't understand what's going on. I've also tried TDM with GCC 5.1.0. Same thing. Anybody have any advice? Is it something screwy with GCC in Windows?
Here is the assembly produced by the compiler (note how the shuffle is turned into a permutation automatically, with vperm2i128 and vpalignr, which is the desired behavior:
GCC Explorer
Minimal program: above.
Desired behavior: print permuted byte vector (which it does in 32-bit mode).
Expected output (works in 32-bit mode):
$ gcc nvec.c -m32 -mavx2 -o a.exe && a.exe
[ 92 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ]
Actual result: crash.
Description of crash: immediate crash, windows error reporting bug shows up. No errors or warnings.
Ok so i have a project, and i have some helper functions which need to be shared in various other files. call it Helper.c /.h , with the corresponding compilation flag to avoid multiple inclusion (#ifndef SymbolName #define Symbolname blah blahblah #endif). Every file has its header file in the following way:
#include ....
#include ....
#ifndef __FILENAME_H__
#define __FILENAME_H__ //in each file(FILENAME is replaced for the current file's name)
declarations of functions, types, etc.
#endif
I have a compare function, called dummyCompare (templates, so when creating a variable of this ADT, you need to supply your own function pointer for it to work, so for some cases i don't need a specific function, just a generic one, so that is what dummyCompare is.
The error i get when compiling is:
gcc ./Helper.c ./LinkedList.c ./ABB.c ./AVL.c -Wall -lm -D DEBUG -g
duplicate symbol _dummyCompare in:
/var/folders/f2/nghjrbz915vbhjw_1gbb65sm0000gn/T//cc75R4sQ.o
/var/folders/f2/nghjrbz915vbhjw_1gbb65sm0000gn/T//cc8jQwyE.o
ld: 1 duplicate symbol for architecture x86_64
collect2: ld returned 1 exit status
List is used for a non-recursive solution for tree operations in ABB(ABB = BST in spanish)/AVL. Now using Sublime Text 2, i get the following search results for "dummyCompare"
Searching 8 files for "dummycompare"
/dir/ABB.c:
81 if (abb != NULL) {
82 if (ABB_getRoot(*abb) != NULL){
83: list = LL_newList(dummyCompare);
84 LL_insert(list, 1, ABB_getRoot(*abb));
85
/dir/AVL.c:
67 if (avl != NULL) {
68 if (AVL_getRoot(*avl) != NULL){
69: list = LL_newList(dummyCompare);
70 LL_insert(list, 1, AVL_getRoot(*avl));
71
/dir/Helper.c:
2
3 /****************************************************************************
4: * dummyCompare *
5 *****************************************************************************
6 * Retorna si 2 dirrecciones son iguales, necesario para el funcionamiento *
7 * de la lista *
8 ****************************************************************************/
9: int dummyCompare(void * a, void * b)
10 {
11 if (a == b)
/dir/Helper.h:
4
5 int getMax(int a, int b);
6: int dummyCompare(void * a, void * b);
7
8 #endif
5 matches across 4 files
Thing is i can't seem to understand what is wrong, and why am I getting this error. Checked a lot of other question, and only answer i found was ("use #ifndef ... "), which I'm using
flex code:
1 %option noyywrap nodefault yylineno case-insensitive
2 %{
3 #include "stdio.h"
4 #include "tp.tab.h"
5 %}
6
7 %%
8 "{" {return '{';}
9 "}" {return '}';}
10 ";" {return ';';}
11 "create" {return CREATE;}
12 "cmd" {return CMD;}
13 "int" {yylval.intval = 20;return INT;}
14 [a-zA-Z]+ {yylval.strval = yytext;printf("id:%s\n" , yylval.strval);return ID;}
15 [ \t\n]
16 <<EOF>> {return 0;}
17 . {printf("mistery char\n");}
18
bison code:
1 %{
2 #include "stdlib.h"
3 #include "stdio.h"
4 #include "stdarg.h"
5 void yyerror(char *s, ...);
6 #define YYDEBUG 1
7 int yydebug = 1;
8 %}
9
10 %union{
11 char *strval;
12 int intval;
13 }
14
15 %token <strval> ID
16 %token <intval> INT
17 %token CREATE
18 %token CMD
19
20 %type <strval> col_definition
21 %type <intval> create_type
22 %start stmt_list
23
24 %%
25 stmt_list:stmt ';'
26 | stmt_list stmt ';'
27 ;
28
29 stmt:create_cmd_stmt {/*printf("create cmd\n");*/}
30 ;
31
32 create_cmd_stmt:CREATE CMD ID'{'create_col_list'}' {printf("%s\n" , $3);}
33 ;
34 create_col_list:col_definition
35 | create_col_list col_definition
36 ;
37
38 col_definition:create_type ID ';' {printf("%d , %s\n" , $1, $2);}
39 ;
40
41 create_type:INT {$$ = $1;}
42 ;
43
44 %%
45 extern FILE *yyin;
46
47 void
48 yyerror(char *s, ...)
49 {
50 extern yylineno;
51 va_list ap;
52 va_start(ap, s);
53 fprintf(stderr, "%d: error: ", yylineno);
54 vfprintf(stderr, s, ap);
55 fprintf(stderr, "\n");
56 }
57
58 int main(int argc , char *argv[])
59 {
60 yyin = fopen(argv[1] , "r");
61 if(!yyin){
62 printf("open file %s failed\n" ,argv[1]);
63 return -1;
64 }
65
66 if(!yyparse()){
67 printf("parse work!\n");
68 }else{
69 printf("parse failed!\n");
70 }
71
72 fclose(yyin);
73 return 0;
74 }
75
test input file:
create cmd keeplive
{
int a;
int b;
};
test output:
root#VM-Ubuntu203001:~/test/tpp# ./a.out t1.tp
id:keeplive
id:a
20 , a;
id:b
20 , b;
keeplive
{
int a;
int b;
}
parse work!
I have two questions:
1) Why does the action at line 38 print the token ';'? For instance, "20 , a;" and "20 , b;"
2) Why does the action at line 32 print "keeplive
{
int a;
int b;
}" instead of simply "keeplive"?
Short answer:
yylval.strval = yytext;
You can't use yytext like that. The string it points to is private to the lexer and will change as soon as the flex action finishes. You need to do something like:
yylval.strval = strdup(yytext);
and then you need to make sure you free the memory afterwards.
Longer answer:
yytext is actually a pointer into the buffer containing the input. In order to make yytext work as though it were a NUL-terminated string, the flex framework overwrites the character following the token with a NUL before it does the action, and then replaces the original character when the action terminates. So strdup will work fine inside the action, but outside the action (in your bison code), you now have a pointer to the part of the buffer starting with the token. And it gets worse later, since flex will read the next part of the source into the same buffer, and now your pointer is to random garbage. There are several possible scenarios, depending on flex options, but none of them are pretty.
So the golden rule: yytext is only valid until the end of the action. If you want to keep it, copy it, and then make sure you free the storage for the copy when you no longer need it.
In almost all the lexers I've written, the ID token actually finds the identifier in a symbol table (or puts it there) and returns a pointer into the symbol table, which simplifies memory management. But you still have essentially the same memory management issue with, for example, character string literals.
I think this code and error is self-explanatory, but I don't know why?
Environment:
OS: Mac OS X 10.6.1
Compiler: i686-apple-darwin10-gcc-4.2.1
code:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <netdb.h>
4 #include <sys/socket.h>
5
6 int
7 main(int argc, char **argv)
8 {
9 char *ptr, **pptr;
10 struct hostent *hptr;
11 char str[32];
12
13 //ptr = argv[1];
14 ptr = "www.google.com";
15
16 if ((hptr = gethostbyname(ptr)) == NULL) {
17 printf("gethostbyname error for host:%s\n", ptr);
18
19 }
20 printf("official hostname:%s\n", hptr->h_name);
21
22 for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
23 printf(" alias:%s\n", *pptr);
24
25 switch (hptr->h_addrtype) {
26 case AF_INET:
27 case AF_INET6:
28 pptr = hptr->h_addr_list;
29
30 for (; *pptr != NULL; pptr++)
31 printf(" address:%s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
32 break;
33 default:
34 printf("unknown address type\n");
35 break;
36 }
37 return 0;
38 }
compiler and executed output below:
zhumatoMacBook:CProjects zhu$ gcc gethostbynamedemo.c
gethostbynamedemo.c: In function ‘main’:
gethostbynamedemo.c:31: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
zhumatoMacBook:CProjects zhu$ ./a.out
official hostname:www.l.google.com
alias:www.google.com
Segmentation fault
Why am I getting the format warning and could this be the cause of the segmentation fault?
Please compile your code using -Wall.
include header file for inet_ntop (arpa/inet.h)
read inet_ntop(3) man page and be careful about parameter types.
If I count right, the warning is emitted for this line:
printf(" address:%s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
According to this page, inet_ntop does indeed return char*. However, apparently you don't include <arpa/inet.h> - this can cause this warning, as the compiler may default to interpret an undeclared function as one returning an int.
Next time, please mark the problematic code line(s) with e.g. a comment - it would increase your chances of getting useful answers :-)