Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I have been studying C programming from a book called "The Practice of Programming" by Kernighan and Pike. Based on the material in this book I have written a small program to sort an array of integers given on the command line.
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 30
char *progname;
int arr[MAXSIZE];
int icmp(int *, int *);
int main(int argc, char *argv[]) {
int i;
progname = argv[0];
if (argc == 1) {
fprintf(stderr, "usage: %s [int ...]\n", progname);
exit(1);
}
for (i = 0; argc > 1 && i < MAXSIZE; i++, argc--) {
arr[i] = atoi(argv[i+1]);
}
int n = i;
qsort(arr, n, sizeof(*arr), icmp);
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
exit(0);
}
int icmp(int *p1, int *p2) {
int v1 = *p1;
int v2 = *p2;
if (v1 < v2) {
return -1;
} else if (v1 == v2) {
return 0;
} else {
return 1;
}
}
Yes, my little program seems to work and I am quite happy with it. However, my implementation differs from the one given in the book, which does not seem to sort integers correctly. The authors define icmp() as:
int icmp(const void *p1, const void *p2) {
int v1, v2;
v1 = *(int *) p1;
v2 = *(int *) p2;
if (v1 < v2) {
return -1;
} else if (v1 == v2) {
return 0;
} else {
return 1;
}
}
What's the deal? My version also throws a warning from gcc:
warning: passing argument 4 of 'qsort' from incompatible pointer type
But, the qsort with the correct pointer type is not correctly sorting my ints! Very confused here. If anyone can enlighten me I will be very grateful.
qsort comparison: why const void *?
If you check the prototype of qsort, you'll find:
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
The parameter type of the compar function is const void * as you noticed.
It's void * because qsort is supposed to sort generic type, not just int. You can sort array of double, array of string, array of struct, and so on.
It's const void * to avoid accidental changes to the data that the pointer is pointing to (within that compar function). This is just a typical safety measure of the keyword const.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I have an example code as below, because I'm not familiar with the function pointer so that I cannot find out what is happening at
ret = (p_local->str)(10,b_in); (segmentation fault)
#include "stdio.h"
typedef int (*check)(const int a, char * const b[]);
typedef struct ST_T_COMMAND
{
char *chuoi;
check str;
} T_COMMAND;
const T_COMMAND *p_global;
int main()
{
int ret;
const T_COMMAND *p_local;
char *b_in[] = {"1234", "abchd"};
T_COMMAND str_new;
p_global = &str_new;
str_new.chuoi = "1234";
p_local = p_global;
if(strcmp(p_local->chuoi, b_in[0]) == 0)
{
ret = (p_local->str)(10, b_in);
printf("ret = %d\n", ret);
}
else
{
printf("else\n");
}
return 0;
}
I want to pass that segmentation fault. And please tell me what is wrong with my code
Here
typedef int (*check)(const int a, char * const b[]);
you have declared the function pointer i.e check is the function pointer name, it can points to any function whose input argument are int and char* const [] type & which returns int type.
And here
ret = (p_local->str)(10, b_in); /* calling via function pointer */
you are trying to call via function pointer but you haven't initialized function pointer anywhere. You need to initialize function pointer first before calling it.
Also
const T_COMMAND *p_local; /* initialize it here itself */
above syntax means where p_local points that is constant i.e when you will do like
p_local->str = funHandler;
as I did below, compiler will not allow it to modify.
Same with p_global, if you make this as const earlier, you can't do like
const T_COMMAND *p_global;
p_local = p_global; /* not possible due to above const declaration of p_global */
Try this version:
#include <stdio.h>
#include <string.h>
typedef int (*check)(const int a, char * const b[]);
typedef struct ST_T_COMMAND
{
char *chuoi;
check str;
}T_COMMAND;
T_COMMAND *p_global; /* removed const */
int funHandler(int num, char* const buf[10])
{
printf("in funHandler() %d %s\n", num, buf[0]);
return num;
}
int main(void)
{
int ret;
T_COMMAND *p_local; /* removed const */
char * b_in[] = {"1234","abchd"};
T_COMMAND str_new;
p_global = &str_new;
str_new.chuoi = "1234";
p_local = p_global;
if(strcmp(p_local->chuoi,b_in[0]) == 0)
{
p_local->str = funHandler; /* initialize function pointer, you missed this */
ret = (p_local->str)(10,b_in);
printf("ret = %d\n",ret);
}
else
{
printf("else\n");
}
return 0;
}
ret = (p_local->str)(10,b_in);
You are calling the function p_local->str without initializing it first.
You need to set a value to plocal->str (or any of the equivalent values in your program i.e. p_global, str_new)
This value should be a function that you have defined elsewhere which matches the type of the function pointer i.e. parameters of const int a and char * const b[]
Yesterday I had a test on C where I coudn't figure out the last question:
We were given two arrays of two types of arrays: arrays including consecutive elements that are equal(eg: {"stack","heap","heap"}) and arrays of where no consecutive elements where equal (eg: {1,2,3,4,5,6,7,8,9}).
We were then asked to find one function that returned 1 or 0 if the given array contained doubles or not. So this function had to work with both integer arrays and char * arrays.
This is what I came up with today (but it keeps giving the wrong answer and crashing afterwards or a segmentation fault when comparing the strings)
Edit: correct code (thanks to #BLUEPIXY !)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int contains_dup(void *array, size_t size, size_t sizeoftype, int (*cmp)(const void*, const void*)){
//array != NULL, size != 0
char *obj = array;
size_t i;
for(i = 0; i < size-1; ++i){
if(cmp(obj + sizeoftype * i, obj + sizeoftype * (i+1)))
return 1;
}
return 0;
}
int eqi(const void *a, const void *b){
int x = *(const int *)a;
int y = *(const int *)b;
return x == y;
}
int eqs(const void *a, const void *b){
return strcmp(a, b) == 0;
}
#define TEST(name, cmp)\
do{\
int test;\
puts(#name ":");\
test = contains_dup(name, sizeof(name)/sizeof(*name), sizeof(*name), cmp);\
test ? puts("doubles? Yes\n") : puts("doubles? No\n");\
}while(0)\
/**/
int main(void){
int ints_yes[] = {0,1,2,2,2,3,4,4,5};
int ints_no[] = {0,1,2,3,4,5,6,7,8};
char *strings_yes[]={"heap","stack","stack","overflow"};
char *strings_no[] ={"heap","stack","heap","stack","overflow"};
puts("test:");
TEST(ints_yes, eqi);
TEST(ints_no, eqi);
TEST(strings_yes, eqs);
TEST(strings_no, eqs);
return 0;
}
Wrong old code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int array_contains_doubles(void ** array, int size, int sizeoftype){
int i;
char **out =(char**) malloc(size * sizeof(char*));
for(i=0;i<size;i++){ //trying to convert the array of ints to an
out[i] = array+i*sizeoftype; //array of char * eg: {1,2} ->{"1","2"}
// *out[i] +='a';
printf("%c\n",*out[i]);
}
out[i]= NULL;
while(*(out+1)!=NULL){
if(strcmp(*out,*(out++))==0){ //<- where i get the segmentation error
return 1;
}
}
return 0;
}
int main(void){
int i;
int ints_yes[] = {0,1,2,2,2,3,4,4,5};
int ints_no[]={0,1,2,3,4,5,6,7,8};
char * strings_yes[]={"heap","stack","stack","overflow"};
char * strings_no[]={"heap","stack","heap","stack","overflow"};
int test = array_contains_doubles((void **) ints_no,
sizeof(ints_no)/sizeof(ints_no[0]), sizeof(int));
(test) ? (printf("doubles? Yes")) : (printf("doubles? No"));
}
Sorry for any spelling mistakes, english is not my native language.
What your teacher is likely fishing for, is for you to implement a "functor" similar to the function pointer passed to bsearch (study this function). Something along the lines of this:
typedef int comp_func_t (const void*, const void*);
bool equal (const void* obj1, const void* obj2, comp_func_t* comp)
{
return comp(obj1, obj2)==0;
}
You call equal from your application with a pointer to the objects to compare, no matter what kind of objects they are. The function pointer specifies how objects of this type should be compared. You then implement the comparison functions for each type:
int comp_int (const void* obj1, const void* obj2)
{
int a = *(const int*)obj1;
int b = *(const int*)obj2;
if(a < b)
{
return -1;
}
else if(a > b)
{
return 1;
}
else // a == b
{
return 0;
}
}
int comp_str (const void* obj1, const void* obj2)
{
...
}
Typical use could be:
int x;
int y;
...
if(equal(&x, &y, comp_int))
{
...
}
Now this only compares two objects, so you'll have to expand this for an array by 1) sorting the array and 2) calling it for every two adjacent items in the sorted array, to find out if any are equal.
The above is the old, "de facto standard" way to implement type-specific behavior in C. In newer versions of the language, more elegant ways are available through the _Generic keyword, but this would probably not be addressed on a beginner-level class.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am currently trying to solve a task, which is quite hard for me, a beginner to C, to handle and so i came to this point where I do not know what to do anymore.
My task is to implement polynomials with several functions....
The functions should be clear when you look at the code I think.
My exact problem is that i dont get a compiler error but a Segmentation Fault. I marked where my attempts to debug lead me to. But I have absolutely no clue on what I have to change. I hope someone can help me fix my code.
So here are the three code parts:
Number one: poly.c
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "poly.h"
struct poly_t {
unsigned degree;
int *coeffs;
};
//constructor: heap
poly_t *poly_alloc(unsigned degree){
poly_t *heap_p;
heap_p = malloc(sizeof(*heap_p)+(degree+1)*sizeof(int)); //or malloc(sizeof(*heap_p)*(degree+1)) furthermore not sure if degree or degree +1
}
//free heap
void poly_free(poly_t *p){
int *coeffs = p->coeffs;
free(coeffs);
free(p);
}
void poly_set_coeff(poly_t *p, unsigned deg, int coeff){
p->degree = deg;
p->coeffs += deg;
p->coeffs[deg] = coeff;
//does not work Segmentation Fault not sure what to do
//p->coeffs += deg;
//*p->coeffs = coeff;
printf("%d",*p->coeffs);
}
//different variations
poly_t *poly_linear(poly_t *p, int a1, int a0){
p->degree=1;
*p->coeffs=a1;
p->coeffs++;
*p->coeffs=a0;
p->coeffs--;
}
poly_t *poly_quadratic(poly_t *p, int a2, int a1, int a0){
p->degree=2;
*p->coeffs=a2;
p->coeffs++;
*p->coeffs=a1;
p->coeffs++;
*p->coeffs=a0;
p->coeffs-=2;
}
//evaluate using horner
int poly_eval(poly_t const *p, int x){
int d = p->degree;
int next;
int adr = *p->coeffs;
int *arr = p->coeffs;
int res = arr[d];
for(int i=0; i<=d; i++){
adr+=(d-i);
next = arr[adr];
adr-=(d-i);
res = res*x+next;
}
return res;
}
//constructor : .txt
poly_t *poly_alloc_d(){
//needs to be finished
}
Number Two: main.c
#include <stdlib.h>
#include <stdio.h>
#include "poly.h"
int main(int argc, char** argv){
if(argc<3){
fprintf(stderr, "syntax: %s x coeffs...", argv[0]);
return 1;
}
poly_t *p = poly_alloc(argc-3);
for(int i = 2; i<argc; i++){
int coeff = atoi (argv[i]);
poly_set_coeff(p, i-2, coeff);
}
return 0;//for debugging
int x=atoi(argv[1]);
int y=poly_eval(p,x);
poly_free(p);
printf("%d\n", y);
return 0;
}
And at last my header file:
poly.h
#ifndef POLY_H
#define POLY_H
/* unvollständiger Verbund */
typedef struct poly_t poly_t;
poly_t *poly_alloc(unsigned degree);
void poly_free(poly_t *p);
void poly_set_coeff(poly_t *p, unsigned deg, int coeff);
int poly_eval(poly_t const *p, int x);
#endif /* POLY_H */
I appreciate every help. I hope you can help me sort this out and please be patient with me a newbie to C...
Thanks in advance
You have not allocated or freed memory correctly, and the function didn't even return the pointer! I think you were trying to allocate one block of memory for the struct and the array it contains, but the struct does not contain an array: only a pointer to an array. You have to allocate them separately:
typedef struct {
unsigned degree;
int *coeffs;
} poly_t;
//constructor: heap
poly_t *poly_alloc(unsigned degree){
poly_t *heap_p;
heap_p = malloc(sizeof(*heap_p));
if (heap_p == NULL)
exit (1); // allocation error
heap_p->coeffs = malloc(degree * sizeof(int));
if (heap_p->coeffs == NULL)
exit (1); // allocation error
return heap_p;
}
//free heap
void poly_free(poly_t *p){
free(p->coeffs);
free(p);
}
There are other mistakes too, for example
p->coeffs += deg;
You mustn't play with the allocated memory pointer, you already did it correctly like this
p->coeffs[deg] = coeff;
although you can use an intermediate pointer if you want:
int *ptr = p->coeffs + deg;
*ptr = coeff;
Having trouble getting my head around implementing the qsort() built into C to sort an array of structs by a stored int value (hitCount).
My struct:
typedef struct words {
const char *word;
int hitCount;
} words;
I'm trying to use the example given by Microsoft (http://support.microsoft.com/kb/73853).
So I've got at the top:
typedef int (*compfn)(const void*, const void*);
and the comparision method:
int compare (words *a, words *b) {
if (a->hitCount > b->hitCount) {
return -1;
} else if (a->hitCount < b->hitCount) {
return 1;
} else {
return 0;
}
}
then within another method I call qsort with my array name and other details replacing the Microsoft example:
qsort((void *) &output, outputLength, sizeof(words), (compfn)compare);
This gives a segmentation fault.
I don't fully understand how to use qsort so I assume where I've adapted it from Microsoft's example I've done it incorrectly.
I hope I've included the mistake and can get some enlightenment as to what I should be doing in order for this to work correctly.
Many Thanks!
You have to pass the array not the address of the array to qsort.
qsort( output, ... );
Also your compare function must return an int and accept two const void* arguments.
Casting your function int compare (words *a, words *b) to a different( yet correct ) type which is then called by qsort() will cause undefined behaviour.
The compare function must be:
int compare (const void *a, const void *b)...
Then you cast a and b to correct types:
((words*)a)->hitCount < ((words*)b)->hitCount
I suspect that outputLength is computed incorrectly. A complete working example:
#include <stdio.h>
#include <stdlib.h>
typedef struct words {
const char *word;
int hitCount;
} words;
int compare(const void * left, const void * right) {
const words * a = (const words *) left;
const words * b = (const words *) right;
if (a->hitCount > b->hitCount) {
return -1;
} else if (a->hitCount < b->hitCount) {
return 1;
} else {
return 0;
}
}
int main() {
struct words output[] = {
{ "hello", 314 },
{ "world", 42 },
{ "answer", 42 }
};
int outputLength = sizeof(output) / sizeof(output[0]);
int i;
output[0].word = "hello";
output[0].hitCount = 314;
output[1].word = "world";
output[1].hitCount = 42;
qsort(output, outputLength, sizeof(words), compare);
for (i = 0; i < outputLength; ++i) {
printf("%d %s\n", output[i].hitCount, output[i].word);
}
return 0;
}
The prototype of the standard library function qsort is
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Note the signature of the compare function. You cannot typecast a pointer to a function of different signature and make it work correctly. Therefore, typecasting your compare function will not work. It must have the same signature as declared in the prototype of qsort. Change your compare function to -
int compare(const void *a, const void *b) {
int c = ((words *) a)->hitCount;
int d = ((words *) b)->hitCount;
if(c > d) return -1;
if(c < d) return 1;
return 0;
}
The first argument base of qsort is the base address of the buffer which contains the elements to be sorted. Also, any pointer type is assignment compatible to a void * variable and as such you don't need to cast the base address. Therefore, you should call the qsort function as -
qsort(output, outputLength, sizeof output[0], compare);
Got it working with:
int compare (const void *a, const void *b) {
if (((words *)a)->hitCount > ((words *)b)->hitCount) {
return -1;
} else if (((words *)a)->hitCount < ((words *)b)->hitCount) {
return 1;
} else {
return 0;
}
}
and call to sort:
qsort(output, outputLength, sizeof(words), compare);
Thanks to everyone's help but majority credit to "self".
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
If I have a function
int foo() {
/* stuff */
}
to which I want to send arguments (in spite the fact that it's a bad practice):
int main(void) {
int arg1 = 3;
int arg2 = 4;
foo(arg1, arg2);
return 0;
}
then, how can I refer to the arguments arg1 and arg2 inside foo()?
What's wrong with int foo(int arg1, int arg2);?
If you're unsure about the number of arguments you will be passing look into variadic functions.
This is not exactly what you want and is completely unportable but it illustrates
the principle. You probably have to adjust the offsets and the offsets will be different if the calling function (main in this case) has other variables on the stack.
And of course, if the target platform has a stack that grows in the other direction you'd have to change the loop to count down p instead.
#include <stdio.h>
int foo(void) {
int *p;
int a, b;
int i;
for (i = 0; i < 32; i++) {
p = (&i + i);
printf("i %d : p %p %d\n", i, p, *p);
}
a = *(&i + 11);
b = *(&i + 10);
printf("a %d\n", a);
printf("b %d\n", b);
return a + b;
}
int main(void) {
int a = 8;
int b = 2;
foo();
return 0;
}
And for the record, this kind of stuff is both fun and useful. In particular, it can be invaluable to know when debugging. So I think the question is a good one. That does not mean that this kind of thing should ever end up in any "production" code.
You can solve it by having a global state and a helper function:
static int foo_i, foo_j;
static void foo_setup(int i, int j) {
foo_i = i; foo_j = j;
}
int foo() {
return foo_i % foo_j;
}
int main() {
foo_setup(10,40);
printf("%d\n", foo());
}
To decide whether this is suitable for you, you must consider that this solution is non-reentrant. If you are using threads, you may need to synchronise the calls to foo_setup and foo. Similarly, if you will not call foo immediately after calling foo_setup, you need to carefully craft your code to not use code calling foo_setup, in between.
If you can use c++, you can pass the arguments through the constructor and define an operator() method for the struct.
Thank you for the suggestions. The solution I suggest for the problem I introduced is as follows:
static int helper(int argc, ...) {
unsigned *argv = (unsigned *) (void *)(&argc + 1);
switch (argc) {
case 0: /* do stuff */
case 1: /* do stuff with argv[0] */
case 2: /* do stuff with argv[0], argv[1] */
...
case n: /* do stuff with argv[0], argv[1], ..., argv[n] */
}
}
int goo(void) {
return helper(0);
}
int bar(int arg1) {
return helper(1, arg1);
}
int foo(int arg1, int arg2) {
return helper(2, arg1, arg2);
}
int main(void) {
int arg1 = 3;
int arg2 = 4;
return foo(arg1, arg2);
}