I am trying to write some C code, and while running the following, my compiler terminates abruptly, after printing 'A'. Why?
//report expected thing
void Expected(char *s){
int i=0;
int n = sizeof(s)/sizeof(s[0]);
while (i< n)
printf ("%c", s[i]);
printf(" expected.\n");
}
int main(int argc, char *argv){
printf("%c",65); //after this compiler hangs and asks for exit abnormally
char *Arr ={'a'};
Expected(Arr);
return 0;
}
Also, if I put
char *Arr ={"a"}; //note the double quotes
then it starts printing out infinite number of 'a's. Why should this happen?
int n = sizeof(s)/sizeof(s[0]);
is not how to get the length of the array of which the pointer passed as the argument points at the first element.
Pass the size of the array if you want to let your function know that.
char *Arr ={'a'};
Is not good because 'a' is a integer and you converted it to a pointer, then the result has too little chance to be a valid pointer.
char *Arr ={"a"};
is OK because it is a valid pointer, but it will be infinite loop because i is not updated in the while loop.
The type of main() function is implementation-defined. You should use standard type unless you have some reason to use special main().
Your code should be like this:
#include <stdio.h>
//report expected thing
void Expected(const char *s, size_t n){ /* add const because the contents of array won't be modified */
size_t i=0; /* use size_t to match type of n */
while (i < n)
printf ("%c", s[i++]); /* update i */
printf(" expected.\n");
}
int main(void){ /* use standard main(). int main(int argc, char **argv) is the another standard type */
printf("%c",65); //after this compiler hangs and asks for exit abnormally
char Arr[] ={'a'}; /* declare an array instead of a pointer */
Expected(Arr, sizeof(Arr)/sizeof(Arr[0]));
return 0;
}
Finally, if it is really not your produced executable but your compiler that is crashing, throw the broken compiler away and get a new one.
Related
Background: My original main() is:
int main(int argc, char *argv[])
{
unsigned char output[16] = {0x00}; // copied from code
// .... (some steps to calculate output[i])
for (i = 0; i < 16; i++)
{
printf("%02X ", output[i]); // output[i] is an array of 16-byte hex values
}
return 0;
}
The original program (e.g., calculate.c) is run by command line:
./calculate $(echo "this_is_input"|xxd -p)
Now I want to modify main() as a call function only, e.g., named run(). And write a new main() to call run() function.
The input (equivalent to above command line) is hardcoded in new main(). main() will pass the input value to run() function (instead of using above command line).
run(int argc, char *argv[])
{
....
return output[i];
}
then run() returns the same output[i] to main()
int main()
{
input_char = **equivalent to $(echo "this_is_input"|xxd -p)** // how to define?
unsigned char returned_output[16] = {0x00};
returned_output = run(X, input_char);
print(returned_output);
}
Question:
How to present the hex dump value of $(echo "this_is_input"|xxd -p)** in the main()?
How to modify run() and main() in order to return unsigned char array to main()?
How to present the hex dump value of $(echo "this_is_input"|xxd -p)** in the main()?
You can represent it as an array of characters, or for example an array of arrays of characters - tokenised by whitespace. Latter is the representation that the command line arguments are already in argv.
How to modify run() and main() in order to return unsigned char array to main()?
You must declare the return type of the function. It is not possible to return an array directly in C, and it is undesirable to copy arrays around. A typical solution is to let the caller (main) create the array, and let the called function modify the content of the array:
void run(int argc, char *argv[], unsigned char output[16])
main has a problem. It attempts to assign an array. Arrays are not assignable. Given that arrays cannot be returned from functions either, this makes little sense.
This is how to call run that I've suggested:
unsigned char output[16] = {0x00};
run(argc, argv, output);
/*implementation of strrev i.e. string reverse function*/
#include<stdio.h>
#include<string.h>
/*length of the string i.e. cells in the string*/
static const unsigned int MAX_LENGTH = 100;
//static const int MAX_LENGTH = -100;
/*reverses the string*/
void reverseString(char[]);
/*swaps the elements in the cells of a string*/
void swap(char[], int, int);
/*runs the program*/
int main()
{
char string[MAX_LENGTH];
//char string[0]; //no error!
//char string[-1]; //error!
gets(string);
reverseString(string);
printf("\n%s", string);
return 0;
}
void reverseString(char string[])
{
int i;
for(i = 0; i < (strlen(string) / 2); i++)
{
swap(string, i, (strlen(string) - 1 - i));
}
}
void swap(char string[], int i, int j)
{
int temp = string[i];
string[i] = string[j];
string[j] = temp;
}
Look at the main function. If you replace the first line "char string[MAX_LENGTH];" with "char string[-1];", the compiler shows error. (because string of negative length makes no sense). However, if you replace the 7th line of this code (where I declared const MAX_LENGTH) with the code written in comments in line 8 (in which MAX_LENGTH is assigned a -ve value), there is no compilation error. Why?
Also, why there is no error in declaring zero length string. How does zero length string makes sense to compiler but not a negative length string?
Because it's not the same thing.
In the first case, you're defining an array, using a fixed, compile-time size
In the second case, you're defining a variable length array or VLA.
The compiler does the allocation at run time in the second case (with this -100 value it isn't going to end well), because the const isn't really a constant in C, it just tells the compiler you aren't to change the value (and also allows some optimizations). So the result is undefined behaviour (more here: Declaring an array of negative length)
If you want the same behaviour use a #define
#define MAX_LENGTH -100 // will raise a compilation error
or as suggested in comments, an enumerated constant:
enum { MAX_LENGTH = -100 }; // will raise a compilation error
If you want to protect your declarations, use assert
assert(MAX_LENGTH > 0);
char string[MAX_LENGTH];
As for the zero-length element, no need to repeat what's already been answered: What's the need of array with zero elements? (in a nutshell, it's useful at the end of a structure to be able to have varying length)
void check_vertical_win(char A[rows][columns]){
int i,j;
char *str1=A[i][j];
char *str2=A[i-1][j];
char *str3=A[i-2][j];
char *str4=A[i-3][j];
int elegxos1;
int elegxos2;
elegxos1=strcmp(str1,str2);
elegxos2=strcmp(str3,str4);
for(j=0;j<6;j++){
for(i=6;i>=3;i--){
if(elegxos1==0 && elegxos2==0){
printf("\nBill is the winner.\n");
}
}
}
}
I want to check if two strings in a matrix are equal,so i'm using the function strcmp. However the compiler gives warning: Initialization makes pointer from integer without a cast.
(Then when i run the programme it says: Windows are checking for a solution at my problem).
I've tried a lot to find my mistake looking other similar programmes but i can't find out.
void check_vertical_win(char A[rows][columns])
This takes a matrix of chars. If you have a matrix where each entry is a string, it should be:
void check_vertical_win(char* A[rows][columns])
Also, you're using variables i and j before they are initialized (they contain garbage):
int i,j;
char *str1=A[i][j];
char *str2=A[i-1][j];
char *str3=A[i-2][j];
char *str4=A[i-3][j];
I've written a code that sums up integers brought in from the command line:
#include <stdio.h>
int main(int argc, int* argv[]) {
int i, s=0;
for (i=1;i<argc;i++)
s=s + *argv[i];
printf("Sum: %d\n", s);
return 0;
}
The best part is, it passes the gcc compiling process, but when I actually run it and insert the numbers, the result seems I somehow breached the range of int.
It seems that you are compiling your code in C89 mode in which s is taken as int by default by compiler. s is uninitialized therefore nothing good could be expected. If fact it will invoke undefined behavior.
Note that argv[i] is of char * type (change your main signature) and you need to convert it to int before adding it to s.
The 2nd argument of main should be either of type char** or of type char*[] and not int*[]. So, *argv[i] is of type char. Instead of getting each character, you can get each string(argv[i] which is of type char*) and then extract the number from it and assign it to a variable, say num. This can be done by using the sscanf function:
#include <stdio.h>
int main(int argc, char* argv[]) { //int changed to char here
int i, s=0,num;
for (i=1;i<argc;i++)
if(sscanf(argv[i],"%d",&num)) //if extraction was successful
s=s + num;
printf("Sum: %d\n", s);
return 0;
}
Assuming you have s initialized properly as shown below.
Along with this the prototype of your main() should be as shown below inorder to get the command line arguments.
int main(int argc, char **argv)
{
int s =0;
// Check for argc matches the required number of arguments */
for(i=1;i<argc;i++)
s=s + atoi(argv[i]); /* Use atoi() to convert your string to integer strtol() can also be used */
printf("%d\n",s);
return 0;
}
PS: Using uninitialized variables lead to undefined behvaior
I am relatively new to C. I have encountered quite a few segmentation faults but I was able to find the error within a few minutes. However this one's got me confused. Here's a new function I was trying to write. This basically is the C equivalent of the python code
r=t[M:N]
Here's my C code with a test case
#include <stdio.h>
char* subarraym(char* a, int M, int N)
{
char* s;
int i;
for (i=M; i<N; i++){ s[i-M]=a[i]; }
return s;
}
main()
{
char* t="Aldehydes and Ketones";
char* r=subarraym(t,2,10);
printf("%c\n",r[4]);
return 0;
}
The expected answer was 'd'. However I got a segmentation fault.
Extra Info: I was using GCC
Your code will not work because your sub-array pointer is never initialized. You could copy the sub-array, but then you will have to manage the memory, and that's overkilling for your problem.
In C, arrays are usually passed around as pairs of pointer and number of elements. For example:
void do_something(char *p, int np);
If you follow this idiom, then getting a sub-array is trivial, assuming no overflow:
void do_something_sub(char *p, int np, int m, int n)
{
do_array(p + m, n);
}
Checking and managing overflow is also easy, but it is left as an exercise to the reader.
Note 1: Generally, you will not write a function such as do_something_sub(), just call do_something() directly with the proper arguments.
Note 2: Some people prefer to use size_t instead of int for array sizes. size_t is an unsigned type, so you will never have negative values.
Note 3: In C, strings are just like char arrays, but the length is determined by ending them with a NUL char, instead of passing around the length. So to get a NUL-terminated substring, you have to either copy the substring to another char array or modify the original string and overwrite the next-to-last char with the NUL.
From
...,10);
you expect to receive 10 char (+1 0-terminator), so provide it to the function somehow.
Not doing so, but writing to invalid memory by
char * s; /* note, that s is NOT initialised, so it points "nowhere". */
...
s[i-M] = ...
provokes undefined behaviour.
Possible solution to provide memory for such a case can be found in this answer: https://stackoverflow.com/a/25230722/694576
You need to secure the necessary memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* subarraym(char *a, int M, int N){
if(N < 0){
N += strlen(a);
if(N < 0)
N = 0;
}
int len = N - M;
char *s =calloc(len+1, sizeof(char));//memory allocate for substring
return memcpy(s, &a[M], len);
}
int main(){
char *t="Aldehydes and Ketones";
char *r=subarraym(t,2,10);
printf("%c\n",r[4]);
free(r);
return 0;
}