Compile multiple .c files in xcode - head first - c

My question is regarding an exercise of the book which I am using for learning C; head first. In the exercise we are learning to share functions between certain .c files. I am working in Xcode 8.2.1 and wanted to know whether Xcode can compile this exercise for me. I've got it to work correctly with the terminal, but I was wondering whether Xcode allows this compilation and that I've just got something wrong in my properties or something.
The program is a simple XOR-encryption program.
This are the files:
main.c:
#include <stdio.h>
#include "encrypt.h"
int main()
{
char msg[80];
printf("Type your message to be encrypted:\n");
while (fgets(msg, 80, stdin)) {
encrypt(msg);
printf("The encrypted message is like this: %s\n", msg);
encrypt(msg);
printf("The encrypted message is decrypted as: %s\n",msg);
printf("Type your message to be encrypted:\n");
}
}
encrypt.h:
#ifndef ENCRYPT_H_
#define ENCRYPT_H_
void encrypt(char *message);
#endif
encrypt.c:
#include "encrypt.h"
void encrypt(char *message)
{
while (*message) {
*message = *message ^ 31;
message++;
}
}
Now I get an error in the main.c file saying that there is a conflicting type for the function encrypt. This says to me that it sees encrypt as an int-valued function (by default). I think the problem is that the program does not see the encrypt function correctly, however I've given it acces to the correct header file with the correct declaration etc. So that makes me think there is some compiler problem.
Edit: The error messages are:
Semantic Issue Group:
PATH/message_hider/encrypt.h:9:6: Conflicting types for 'encrypt'
PATH/message_hider/main.c:17:9: Implicit declaration of function 'encrypt' is invalid in C99

Related

Catching Missing Semicolons in C header file prototypes

This topic ought to have been flogged to death. I just spent 30 minutes locating what ended up being a missing semicolon at the end of a function prototype in a header file:
void foo(void);
void bar(void) // <<< Error on this line
void squee(void);
This is a common typo caused by copy-pasting the prototype from the C file. Of course according to the compiler the universe just fell apart, with an endless stream of absolutely nonsensical errors, none of them helpful.
This could be avoided by having an optional parsing phase to check for this condition in .h files then report a warning (promoted to error if settings mandate). This would require some restrictions on what you put in header files (no code, consistent format for prototypes, etc). But that's an easy compromise.
I can write my own SW tool to do this, but it would be more helpful to run it as a part of the build process. I use GCC in Eclipse. Any advice on where you'd start with this? Or anything pre-existing / off the shelf? Or perhaps just a better way to approach it?
Thank you.
it's far more common and more difficult to guess the following problem (in a header file):
struct something {
type1 var1;
type2 var2;
}
/* EOF */
and when you #include "header.h" into hello.c
#include <stdio.h>
#include "header.h"
int main(int argc, char **argv)
{
printf("Hello, world\n");
}
you get an error e.g.
lcu#europa:~$ gcc main.c
main.c:4:1: error: expected ';', identifier or '(' before 'int'
4 | int main(int argc, char **argv)
| ^~~
and the compiler has got out of header.h to signal the error in the line of main function. The thing can be worse if you happen to use legacy code and declare main() the old way:
main(argc, argv)
char **argv;
{
...
because then, the struct is a valid type and it is taken as the type returned by main() and you get (if you get it) the error far below (or no error at all, just a warning):
lcu#europa:~$ gcc main.c
main.c: In function 'main':
main.c:4:1: warning: type of 'argc' defaults to 'int' [-Wimplicit-int]
4 | main(argc, argv)
| ^~~~
In this case, the contents of main.c were:
#include <stdio.h>
#include "header.h"
main(argc, argv)
char **argv;
{
printf("Hello, world\n");
}
which is still valid c code.
(these examples were made by gcc, because clang ---the native compiler of freebsd--- detects the EOF in the header file and shows a warning stating that the type was not ended before the end of the include file. But this only happens if the type definition is the last of the file.
Note:
if you declare main as:
#include <stdio.h>
#include "header.h"
main(argc, argv)
int argc;
char **argv;
{
printf("Hello, world\n");
}
you get a complete compilation, without even a warning.

Error in C program when using a C file in #Include directive (Multiple definition error)

Scenario :
A C application created in Netbeans IDE with below two files:
some_function.c
#include <stdio.h>
int function_1(int a, int b){
printf("Entered Value is = %d & %d\n",a,b);
return 0;
}
newmain.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
//function_2(); //Error //function name not allowed
function_1();
function_1(1);
function_1(1,2);
return (EXIT_SUCCESS);
}
When learning the need of the header file in a C program, I tried the above application (as it is). It got compiled and gave the output as below
Entered Value is = 4200800 & 102
Entered Value is = 1 & 102
Entered Value is = 1 & 2
Question 1 : (I realize, in starting stage, to understand the process of the linker program is tough, hence i ask this question.) Is my assumption correct, that when linking, "the linker will check for the function name and not the arguments" in a condition the header file not used?
Regarding the header file usage, I came across this link and there it said as, we can include the C file itself using the #include. So, I used the below line in the file newmain.c
#include "some_function.c"
As expected it shown the below error
error: too few arguments to function 'function_1()'
error: too few arguments to function 'function_1(1)'
And also, I got the below (unexpected) error:
some_function.c:8: multiple definition of `function_1'
some_function.c:8: first defined here
Question 2: What error I did when including the 'c' file itself, as it gives the above said (unexpected) error?
You are probably using a pre-C99 dialect of C, which has "implicit function declarations". This means that functions without declarations are taken to have this kind of signature:
int function_1();
i.e. returning an int and accepting any number of arguments of any type. When you pass an argument list that is incompatible with your function definition, you invoke undefined behaviour at runtime.
Concerning the multiple definition errors, think of it. Each translation unit you include some_function.c will have its own definition of the function. It is as if you had written that definition in every other .c file. C doesn't allow multiple definitions in a program/library.
I (the questioner) post this answer for a quick understanding for some C programming starters. This answer inspired from the answers by #juanchopanza & #Sam Protsenko which are in this post.
Question 1 :Implicit function declarations in C
Question 2:
When using the below line
#include "some_function.c"
The result application will change like below after the preprocessor activity
some_function.c
#include <stdio.h>
int function_1(int a, int b){
printf("Entered Value is = %d & %d\n",a,b);
return 0;
}
newmain.c
#include <stdio.h>
#include <stdlib.h>
/*"#include "some_function.c"" replace begin by preprocessor*/
#include <stdio.h>
int function_1(int a, int b){
printf("Entered Value is = %d & %d\n",a,b);
return 0;
}
/*"#include "some_function.c"" replace end by preprocessor*/
int main(int argc, char** argv) {
//function_2(); //Error //function name not allowed
//function_1(); //Error
//function_1(1); //Error
function_1(1,2);
return (EXIT_SUCCESS);
}
Note : In the above two file, the function function_1 is there in two places
So now the below error is meaningful
some_function.c:8: multiple definition of `function_1'
some_function.c:8: first defined here

Conflicting types for 'sleep'

Why do I keep getting the error message "Conflicting types for 'sleep'" when I try running my program?
#include <stdio.h>
#include <stdlib.h>
void congratulateStudent (char *student, char *course, int numDays)
{
printf("%s has done as much %s Programming as I could fit into %d days. \n", student, course, numDays);
}
int main(int argc, const char * argv[])
{
congratulateStudent("Mark", "Cocoa", 5);
sleep(2);
congratulateStudent("Bo", "Objective-C", 2);
sleep(2);
congratulateStudent("Mike", "Python", 5);
sleep(2);
congratulateStudent("Ted", "iOS", 5);
return 0;
}
Every library function has a corresponding header file that declares the function. For the sleep function, that header file is unistd.h. The documentation for each function tells you which header file to use.
If you don't include the correct header file, then the compiler will complain bitterly. Don't make the compiler unhappy, always include the correct header file.

Login simulator in c, dereferencing incomplete types errors

As a preporatory task for a computer lab in school, we are asked to write a c program that simulates the login process in UNIX. The program should read username and password from a terminal, compare it to hashed values in a local file that is supposed to resemble /etc/passwd.
Here's what I've got:
/*
* Program mylogin.c
*
* This program prompts the user for a login name and password
*
*/
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include <string.h>
/* define some error constants */
#define NOUSER -1
/* define max size of a username */
#define USERNAME_SIZE 32
#define PASSWORD_SIZE 32
#define HASH_SIZE 32
#define FAILED_LIMIT 5
#define AGE_LIMIT 10
int read_username(char *username)
{
printf("login: ");
fgets(username,USERNAME_SIZE,stdin);
/* remove the CR included by getline() */
username[strlen(username)-1]='\0';
return(0);
}
int read_password(char *password)
{
printf("password: ");
fgets(password,PASSWORD_SIZE,stdin);
//getpass(password);
/* remove the CR included by getline() */
password[strlen(password)-1]='\0';
return(0);
}
int user_exists(const char *username)
{
struct pwdb_passwd *pw_entry;
pw_entry=getpwnam(username);
return((pw_entry)!=NULL);
}
int main(int argc,char **argv)
{
char username[USERNAME_SIZE];
char* password;
/* write "login:" and read user input */
read_username(username);
read_password(password);
if (!user_exists(username))
{
printf("Unknown user or authentication\n");
main(argc, argv);
}
struct pwdb_passwd *pw_entry = getpwnam(username);
char* hashed_password = crypt(password,pw_entry->pw_passwd);
if(strcmp(hashed_password, pw_entry->pw_passwd)==0)
{
if((pw_entry->pw_failed)<FAILED_LIMIT)
{
printf("User authenticated successfully\n");
pw_entry->pw_age++;
pw_entry->pw_failed = 0;
pwdb_update_user(pw_entry);
}else{
printf("User account locked\n");
main(argc, argv);
}
}
else
{
printf("Unknown user or authentication\n");
pw_entry->pw_failed++;
if(pw_entry->pw_failed>5){
printf("Too many failed attempts. Username now locked\n");
}
pwdb_update_user(pw_entry);
main(argc, argv);
}
return(0);
}
The struct pwdb_passwd is defined in the files pwdb_lib.c and pwdb_lib.h, which are already written.
When I compile the program, I get a couple of errors. For example on line 73, I get: "error: dereferencing pointer to incomplete type"
I don't understand why. It doesn't seem to like pw_entry->pw_passwd and things like that. More to the point, I get different errors when compiling under Windows with Code::Blocks (using gcc) than under Ubuntu with gcc. I find this pretty strange. I suspect it could be because I import pwd.h and that it only exists on Linux and not Windows. Could this be right? I tried creating my own pwd.h file and save it in the same directory, but it still didn't work. Moving to an ubuntu computer, I dont get errors from the pwd.h thing, but instead get errors on: "dereferencing pointer to incomplete type"
What's wrong with my code?
I also suspect memory leak in the user_exists function, but I'm not sure if it affects the overall program.
Even though pwdb_lib.c is already written, you need to include it in your source file.
Add
#include "pwdb_lib.h"
to your source and make sure you compile/link against pwdb_lib.c
By #includeing this file, you let your source file know about the definitions within it without providing it the implementation. At the end, when you compile your program with pwdb_lib.c (or link its object file, if that's what you're doing), you let any source which included these definitions know where they are implemented (and thus, give them the ability to use them).
If the header is named pwdb_lib.h, then why isn't your program doing an #include of it? It seems to include a different header (pwd.h), which is it?
The error you're getting is the one you'd expect if the declarations were missing.

implicit declaration of functions?

I'm still learning C and I understand that to get rid of most implicit declaration warnings, you add the prototype header at the beginning. But I'm confused as to what you do when you have outside methods being used in your code.
This is my code when I'm using the outside methods
#include <stdio.h>
#include <string.h>
int main(void)
{
int arrayCapacity = 10;
int maxCmdLength = 20;
int A[arrayCapacity];
int count = 0; /* how many ints stored in array A */
char command[maxCmdLength + 1];
int n;
while (scanf("%s", command) != EOF)
{
if (strcmp(command, "insert") == 0)
{
scanf("%d", &n);
insert (n, A, arrayCapacity, &count);
printArray(A, arrayCapacity, count);
}
else if (strcmp(command, "delete") == 0)
{
scanf("%d", &n);
delete(n,A,&count);
printArray(A, arrayCapacity, count);
}
else
{
scanf("%d", &n);
printArray(A, arrayCapacity, count);
}
}
return 0;
}
The methods printArray, insert, and delete are all in the form of: printArray.o, insert.o, delete.o
This is how I compiled my program: gcc -Wall insert.o delete.o printArray.o q1.c
and I get these warnings:
q1.c: In function âmainâ:
q1.c:20: warning: implicit declaration of function `insert'
q1.c:21: warning: implicit declaration of function `printArray'
q1.c:30: warning: implicit declaration of function `delete'
I've tried including this in headers but I get errors saying file or directory not found.
Any help appreciated.
Put them in a header file foo.h like so:
extern void printArray(int *A, int capacity, int count);
...
then include that file in your source
#include "foo.h"
You need to include the correct headers to get rid of such warnings.
If you get a "file not found" error, try to include them as
#include "myheader.h"
and put your header files in the same directory as your source code.
Generally speaking, #include "file" is for programmer-defined headers while #include <file> is or standard headers.
You should be able to just put in the function prototype at the top of the file like you do for other functions in the same file. The linker should take care of the rest.
Where did you get those .o files from? If you have written them yourself, then you should create the corresponding .h files. If you got these files from somewhere else, then you should search for the headers in the same place.
If all called functions are written before the main() function the compiler will know their name, return type and parameter signature and can match all three of these properties with each following function invocation.
Some programmers like to write a function signature first, and do the implementation at a later time.
The only time a function declaration is essential is when using co-routines: functionA invokes functionB which in turn invokes functionA.
Done as follows:
type a(...signatureOfA...)
/* compiler now knows about a() */
type b(...signatureOfB...)
{…
// implementation of b
a(…arguments for a…);
/* compiler knows about above */
…}
type a(...signatureOfA...)i
{…
// implementation of a
b(…arguments for b…);
/* compiler knows about above */
…}
int main()
{
a(… arguments for a…);
/* compiler knows */
return(code);
}

Resources