Just as the follow code,the intcmp1 runs correctly but the intcmp gets a segment fault.I don't know why.These two codes looks as same.
My system environment is: OS X 10.10.2 64bit ; clang
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int intcmp(const void *v1, const void *v2){ //Segment Fault
return (*((int*)(*(int*)v1)) - *((int*)(*(int*)v2)));
}
int intcmp1(const void *v1, const void *v2){ //No Problem
return (**(int**)v1-**(int**)v2);
}
int main(int argc, char *argv[]) {
int a[5]={0,1,2,3,4};
int **b,i;
b=calloc(5,sizeof(int*));
for(i=0;i<5;i++){b[i]=&a[i];}
printf("cmp1 begin\n");
qsort(b,5,sizeof(int*),intcmp1);
printf("cmp1 end\n");
printf("cmp1 begin\n");
qsort(b,5,sizeof(int*),intcmp);
printf("cmp2 end\n");
}
Isn't **((int**)a) equal as *((int*)(*(int*)a))?
No, **((int**)a) and *((int*)(*(int*)a)) are not equivalent. The first one is correct in the context: a is indeed a pointer to an element of the array of int* passed to qsort. **((int **)a) or simply **(int**)a reads the integer you want to compare.
Conversely, the expression *((int*)(*(int*)a)) does something different: it reads from the same address in memory, but as an int and then pretends this int is actually an address and attempts to read from that address. If int and addresses don't have the same width, this will fail spectacularly. It they happen to be the same size, it will succeed non portably.
Furthermore, you cannot reliably compare int values by just subtracting one from the other. For example INT_MIN < 1 but INT_MIN - 1 invokes undefined behaviour and most likely computes to INT_MAX, a positive value.
intcmp1 should be rewritten this way:
int intcmp1(const void *v1, const void *v2) { // works better
return (**(int**)v1 > **(int**)v2) - (**(int**)v1 < **(int**)v2);
}
The < and > comparison operators return 1 or 0, thus imtcmp1 will return -1, 0 or 1 precisely.
Related
I'm trying to make a program that for a given int value keeps the amount of dividers:
int amount_of_dividers and a list of those dividers: int* dividers
This is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int value;
int amount;
int* dividers;
} Divide;
int main(){
Divide ** tt;
read_dividers(tt,5);
}
/* the functions "amount_of_dividers(int g)" and "dividers_of(int g, int amount)"
used in void read_divider are working properly, they are not needed for this question */
void read_divider(Divide *g){
scanf("%d",&(g->value));
g->amount = amount_of_dividers(g->value);
g->dividers = dividers_of(g->value,g->amount);
}
/* assuming that read_divider works, what causes read_dividerS to crash? */
void read_dividers(Divide ** t, int amount){
int i = 0;
t = malloc(amount*sizeof(Divide*));
for(i = 0;i<amount;i++){
read_divider(t[i]);
}
}
Read_dividers uses an array of pointers **t where i'm trying to fill each element of this array with a pointer to a Divide g variable.
EDIT: input in this case in main() : "read_dividers(tt,5)" means the user gives 5 int's, which get converted to 5 Divide structs.
What happens instead is the program crashes after I give in the second int
If any more information is missing, don't hesitate to ask!
You are passing an uninitialized t[i] to read_divider. t is supposed to be pointer to pointer to Divide, not pointer to Divide, you may have just got lucky on your first pass, but I suspect it failed on the very first call.
I'm trying to understand what "best practice" (or really any practice) is for passing a multidimensional array to a function in c is. Certainly this depends on the application, so lets consider writing a function to print a 2D array of variable size. In particular, I'm interested in how one would write the function printArry(__, int a, int b) in the following code. I have omitted the first parameter as I'm not exactly sure what that should be.
void printArry(_____, int a, int b){
/* what goes here? */
}
int main(int argc, char** argv){
int a1=5;
int b1=6;
int a2=7;
int a2=8;
int arry1[a1][b1];
int arry2[a2][b2];
/* set values in arrays */
printArry(arry1, a1, b1);
printArry(arry2, a2, b2);
}
The easiest way is (for C99 and later)
void printArry(int a, int b, int arr[a][b]){
/* what goes here? */
}
But, there are other ways around
void printArry(int a, int b, int arr[][b]){
/* what goes here? */
}
or
void printArry(int a, int b, int (*arr)[b]){
/* what goes here? */
}
Compiler will adjust the first two to the third syntax. So, semantically all three are identical.
And a little bit confusing which will work only as function prototype:
void printArry(int a, int b, int arr[*][*]);
This is not really an answer, but extended comment to the OP's comment question, "well you can pass the array without knowing the number of rows with this, but then how will you know when to stop printing rows?"
Answer: generally, you can't, without passing the array size too. Look at this 1-D example, which breaks the array size.
#include <stdio.h>
int procarr(int array[16], int index)
{
return array[index];
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100));
return 0;
}
Program output (although all elements initialised to 0):
768
That was undefined behaviour and there was no compiler warning. C does not provide any array overrun protection, except for array definition initialisers (although such initialisers can define the array length). You have to pass the array size too, as in
#include <stdio.h>
int procarr(int array[16], size_t index, size_t size)
{
if (index < size)
return array[index];
return -1; // or other action / flag
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100, sizeof arr / sizeof arr[0]));
return 0;
}
Program output:
-1
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;
}
#include <stdio.h>
#include <stdlib.h>
void badf(int n, char c, char* buffer)
{
int i;
for (i=0; i<n; i++)
{
buffer[i]=c;
}
}
void f(int n, char c)
{
char buffer[16];
badf(n,c,buffer);
}
void message ()
{
printf("Hello\n");
}
int main()
{
f(32,0x08048411);
return 0;
}
This is the code I got so far (got given the base of it and got to stick to it, thats why there is a badf and f function)
The goal is that the program prints the Hello message by overflowing to the Instruction pointer. Using Data display debugger in Ubuntu, I believe the address of this display is 0x0804811.
When I run the program through and use x/16x $esp the next address in the stack is just 1s (am guessing only the last two digits are being taken from the address above)
What am wondering is how I would make the next address the full address and not just the last two digits.
Also the 32 is calculated from 16 (buffer defined above) + 8 (base pointer) + 8 (Instruction pointer)
Thanks in advance for any help as I know this specific problem.
Do not pass the address via an 8bit integer (char) but use a type wide enough ... - that is at least 32bits.
Modify as follows:
void badf(int n, unsigned int u, char* buffer)
...
void f(int n, unsigned int u)
...
#include <algorithm>
#include <stdio.h>
#include <iostream>
int intcomp(int *x,int *y) { return *x-*y;};
int a[10000];
int main(void){
int i; int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
qsort(a,n,sizeof(int),intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
it is just copy of code i have two question it show me that intcomp is incompatible in this code
and also what does intcomp function?
and also what is in windows 7 EOF? how tell program that it reached EOF?
the qsort() function requires a pointer with a particular signature.
Your function has the wrong signature so it is complaining.
Your function has the signature:
int intcomp(int *x,int *y)
While qsort requires the signature:
int intcomp(void const* xp,void const* yp)
Please note the difference in the parameter types.
A corrected version of the function is:
int intcomp(void const* xp,void const* yp)
{
// Modified for C as the tag on the question changed:
// int x = *static_cast<int const*>(xp);
// int y = *static_cast<int const*>(yp);
int x = *((int const*)(xp));
int y = *((int const*)(yp));
return x-y;
}
The function qsort() is passed a function pointer as the third parameter.
This function pointer (in your case intcomp()) is used to compare values in the array passed. Each call provides pointers into the array. The result of the function should be:
Less than 0: if x is smaller than y
0: If x is equal to y
Greater than 0: If x is larger than y
First of all: the question is labeled C++ and you #include <algorithm> and <iostream>, but your code is 100% C.
Martin York already gave the answer how to correct the signature of the function you pass to qsort().
However, the "true"(TM) C++ solution would be to use std::sort<> instead of qsort!
#include <algorithm>
#include <stdio.h>
bool intcomp(int a, int b) { return a<b; }
int a[10000];
int main(void){
int n=0;
while (scanf("%d",&a[n])!=EOF)
n++;
std::sort(&a[0], &a[n], intcomp);
for (int i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
Note that incomp() takes ints and not int pointers, and returns a bool. Just like operator<() would.
Also note that in this case, you could forget the intcomp and just use std::sort(&a[0], &a[n]), which will use std::less<>, which will use operator<(int, int).
intcomp is an "Int Compare" function. It is passed a pointer to 2 ints and returns 0 if they are the same, a positive value is x > y and a negative value is x < y.
qsort is passed a pointer to this function and calls it each time it wants to know how to sort a pair of values.
The docs for qsort should give you some more details.
eg http://www.cppreference.com/wiki/c/other/qsort
qsort is in stdlib.h, so include that file at the beginning. Note that algorithm and iostream aren't needed.
#include <stdlib.h>
As Martin York mentioned, qsort needs a function which it will use to compare the values:
void qsort( void *buf, size_t num, size_t size, int (*compare)(const void*, const void *) );
Here is a good example on how to use qsort: http://www.cppreference.com/wiki/c/other/qsort
Edit: Ri was faster....