Comparison of pointer to integer errors in standard C - c

I'm changing my code from variable to pointers and I'm having a bit of trouble. Where it used to work with (largely abbreviated):
int best = 0;
int max = 10;
if (max > best) {
best = max;
}
I'm trying to use pointers so that I can use pass-by reference to abstract it into a function.
int *best;
*best = 0;
int max = 10;
if (max > *best) {
*best = max;
}
I get segmentation faults at the (max > *best) line. Can you tell me where I'm going wrong?

I don't know how it got even that far because of:
int *best;
*best = 0;
You are simply grabbing 4 bytes which have some (unknown to you) previous value, interpreting that as a memory location and writing all zeroes on it.
Longer explanation: int *best gives you use of the name best to refer to a memory location. Trouble is, you have not specified which memory location you want. Since a pointer is nothing more than a number of bytes in memory, and those bytes hold some value (even unused memory holds some value), in effect your new pointer is pointing to an unknown memory location. When you dereference it, bad things happen.
Try it this way:
int someInt = 0;
int* best = &someInt;
*best = 0;
Now you know what memory you are overwriting with zeroes: the piece that was properly reserved for the variable someInt.

In the second example, your best isn't being initialized, thus it will point to an unknown address. You may want to point it to an existing int. For example:
int best = 0;
int *best_ptr = &best; // Now best_ptr points to best
printf("value is %d\n", *best_ptr);
Or maybe allocate memory for it instead:
int *best_ptr = malloc(sizeof(int)); // Allocate
if (best_ptr != NULL) {
*best_ptr = 0;
printf("value is %d\n", *best_ptr);
free(best_ptr); // Deallocate
}

you're assigning an address to the pointer, not a value. Change it to this:
int* pbest;
int best;
pbest = &best;
*pbest = 0;
int max = 10;
if (max > *best) {
*best = max;
}

i think the problem is that you can't assign a integer to a pointer
instead , you should assign a position to a pointer like
int score;
int *best = &score;
and then you can assign an integer to socre
score = 0;

Related

Releasing pointer memory aswell as pointer itself

A "Deeltal" keeps track of how many dividers an integer has (count) and keeps them in an array (dividers).
Examples:
value = 8 -> count = 3 and dividers = {1,2,4}
value = 10, count = 3, dividers = {1,2,5}
Hope everything is clear, take a look at the following code:
typedef struct{
int value;
int count;
int* dividers;
} Deeltal;
void free_dividers(Deeltal *g){ /*Deletes the int* dividers of a given Deeltal*/
free (g - > dividers);
}
/* the following two functions have the same purpose: deleting the content of a
given amount of "Deeltal" AND deleting the pointer to it aswell*/
void free_amountOfdeeltal(Deeltal *d, int amount){
int i;
for (i = 0; i < amount; i++){
free_dividers(&d[i]);
}
free(d);
}
void free_amountOfdeeltalVersion2(Deeltal **g, int amount){
int i;
for(i = 0; i < amount; i++){
free_dividers(&(*g)[i]);
}
free(*g);
}
If my main looked something like this
int main(void){
/*EDIT 3/11/2017: forgot to allocate memory for *d and initializing g.
Thanks for pointing this out*/
Deeltal g = 0;
g.value = 6; g.count = 3; g.dividers = {1,2,3};
Deeltal *d = malloc(sizeof(Deeltal));
d->value = 6; d->count = 3; d->dividers = {1,2,3};
free_amountOfdeeltal(&g);
free_amountOfdeeltalVersion2(&d);
}
What is the difference between free_amountOfdeeltal and free_amountOfdeeltalVersion2?
Both should do the same thing: releasing the memory of a Deeltal and also deleting the pointer pointing to that memory.
On a sidenote:
How do you delete the memory as well as the pointer?
Not withstanding calling this function with invalid data as pointed out by others .. I'll attempt to answer the question I think you are asking.
On a sidenote: How do you delete the memory as well as the pointer?
You can't really "delete the pointer" in this context as a pointer is simply a variable that is assigned an address. You delete memory that was allocated to you by passing free a pointer to the memory. Note that free does not modify the value of the pointer at all. (It can't because the pointer is passed by value.) After the call to free the pointer still points to the same memory address.
If what you mean is "how can I assign a meaningful value to the pointer to identify that its memory has already been deleted," then you can use the second form of your function:
void free_amountOfdeeltalVersion2(Deeltal **g, int amount);
and set *g to NULL before returning. You can then use this information than the pointer is NULL to identify the memory has already been deleted.
You didn't allocate any memory for d so your pointer doesn't point to any structure. Therefor, you can't access its properties or free its memory because you didn't reserve it in the first place. There's no way this code could come remotely close to compiling.
First of all you should be allocating memory for a "Deeltal" structure like this:
Deeltal *d = malloc(sizeof(Deeltal));
I recommend you go back and relearn how pointers work, as you're doing some really weird stuff there.

Able to Print Expected Results From Uninitialized Array of Pointers to Structures - Confused

My issue is with nums3 array and why the last for-loop actually prints expected results. The nums3 array as I understand it contains an array of pointers to the struct but these pointers have not yet been initialized to any specific instance of a struct. But in this for-loop I can assign values and see the expected results display.
Also, I've read that with the pointer returned by malloc I can use the [index] after the pointer and iterate over the allocated memory. I assume this feature is using the fact it has a type multiplied by some value and it does the division automatically to know how this block of memory is split up and therefore how far to advance to the next index. But I'm still confused as to why I'm getting expected results on that last for-loop when I haven't initialized or pointed those pointers to anything specific.
I know that if I were to add ** and change the to -> then I could operate on those pointers directly, but with the code now I'm able to use the . operator to access structure members. So, without the ** in the nums3 malloc line, what exactly does the pointer returned from malloc return?
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_MAX 5
int main(void)
{
struct number {
int num1;
int num2;
int num3;
};
struct number n;
n.num1 = 5;
printf("n.num1: %d\n", n.num1);
n.num2 = 6;
printf("n.num2: %d\n", n.num2);
n.num3 = 7;
printf("n.num3: %d\n", n.num3);
struct number nums1[5];
struct number* nums2 = malloc(sizeof(struct number) * ARRAY_MAX);
struct number* nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);
int x;
for(x = 0; x <= 5; x++) {
nums1[x].num1 = x;
nums1[x].num2 = x;
nums1[x].num3 = x;
}
int y;
for(y = 0; y <= ARRAY_MAX; y++) {
nums2[y].num1 = x;
nums2[y].num2 = x;
nums2[y].num3 = x;
}
for(y=0; y<=ARRAY_MAX; y++) {
nums3[y].num1 = y;
nums3[y].num2 = y;
nums3[y].num3 = y;
printf("%d ", nums3[y].num1);
printf("%d ", nums3[y].num2);
printf("%d \n", nums3[y].num3);
}
Here is a simpler test case of my question:
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
int main(void)
{
struct number {
int num1;
};
struct number* n = malloc(sizeof(struct number*) * MAX);
int i;
for(i=0; i<MAX; i++) {
n[i].num1 = i;
printf("%d\n", n[i]);
}
free(n);
}
Result of running this code:
jason smith#jasonS-pc ~/src/c
$ ./a.exe
0
1
2
3
4
jason smith#jasonS-pc ~/src/c
$
Questions:
How does n[i] work with n being the pointer returned from malloc? How does C know what to do with n[i]? How does C know how to get to n[i+1]? Does it look at what sizeof() is being called on and divide by however many times it is multiplied and use that result to know where the next cell starts?
Why does n[i].num1 = i; even compile? If all I have done is specify a block of memory containing size for x number of pointers to the struct (pointers which would be smaller than the size of the struct itself) and certainly have not initialized anything to point to an actual instance of this struct. Why isn't this a syntax or some other compiler generated error? What exists at cell n[i] that .num1 is working on? Doesn't n[i] right now just contain a pointer without a valid address since it's not yet initialized? How do we go from that to n[i].num1 = i? Is it valid syntax to do "some memory address".num1 = "some value"?
I understand this is not the correct way to do this, and you all have provided great information, but I'm still puzzled as to why this code even compiles. It just doesn't make sense to me.
In general, if you access memory incorrectly you cannot expect anything. You can't expect to get the right answer, and you can't expect to get the wrong answer. You can't expect your program to crash and you can't expect it to run. Again, it can do anything.
The error here is that you allocated an array of pointers but then chose the wrong type to hold the result.
// This is wrong!
struct number* nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);
You want this:
struct number **nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);
// ^^
Or really, this way is better:
struct number **nums3 = malloc(sizeof(*nums3) * ARRAY_MAX);
Then you have an array of (uninitialized) pointers to play with. For example,
for (int i = 0; i < ARRAY_MAX; i++) {
nums3[i] = malloc(sizeof(*nums3[i]));
nums3[i]->num1 = i;
nums3[i]->num2 = i;
nums3[i]->num3 = i;
}
or...
for (int i = 0; i < ARRAY_MAX; i++) {
nums3[i] = &nums2[i];
}
Whatever you want.
(We're pretending here that malloc() doesn't return NULL which is not guaranteed.)
You are correct by saying you are not allocating enough space as sizeof(struct number) = 12 while sizeof(struct number*) = 8
Malloc finds a free memory according to the size you asked and (if successful) returns you a pointer to the first address (this is virtual memory). If you exceed the size created you enter the realm of unexpected behavior. Meaning you either will be able to write and read data from the memory or you won't and even if you manage to do that, you can accidentally overwrite areas in memory storing other data.
In this case, although printing passed with no special behavior, when you try to free(nums3) you will get an error.
Also, if you will reverse the order of nums2 and nums3 declaration and print nums2 after nums3 loop, you will probably be able to see this corruption of data.
Hope this is helpful

Why can't I use malloc to set array size larger than what is needed?

I am coming from Python so using malloc is new to me. Intuitively the below should work but having syntax issues. In my first line I want to set array size to be a max of 8 ints. In the second line, I want to add those 4 ints. This line is for example only, in production I will have user input up to an 8-digit number. When I go to compile (clang) I get size of array has non-integer type 'void *' If I comment out this first line and initialize with the second line (and adding int type) the code works. So I am obviously setting the size incorrectly. Any ideas?
int main(void)
{
int mult_digits[malloc(8 * sizeof(int))];
mult_digits[] = {1,2,3,4};
int size_mult = sizeof mult_digits / sizeof *mult_digits;
printf("Size of the array is %d\n", size_mult);
return 0;
}
This code is all wrong. You call malloc to allocate memory, and malloc returns a pointer. Rather than deconstructing your syntax, which is very broken, I'll give a couple of variants of your program.
int main(void)
{
int mult_digits[] = {1,2,3,4};
int size_mult = sizeof mult_digits / sizeof *mult_digits;
printf("Size of the array is %d\n", size_mult);
return 0;
}
Here the array is not allocated dynamically. It's a local variable with automatic, stored on the stack.
For dynamic allocation you would do this:
int main(void)
{
int *mult_digits = malloc(4*sizeof *mult_digits);
mult_digits[0] = 1;
mult_digits[1] = 2;
mult_digits[2] = 3;
mult_digits[3] = 4;
free(mult_digits);
return 0;
}
The argument to malloc is the number of bytes to be returned. The value returned is the address of the new block of memory. Note also here that we made a call to free to deallocate the memory. If you omit that, the memory will be leaked.
With this variant, there is no way to recover the length of the array from mult_digits. I know that might freak you out, coming from Python, but I repeat. There is no way to recover the length of the array from mult_digits. It's your job to keep track of that information.
Now, you wanted to over-allocate the memory. You can certainly do that:
int main(void)
{
int *mult_digits = malloc(8*sizeof *mult_digits);
mult_digits[0] = 1;
mult_digits[1] = 2;
mult_digits[2] = 3;
mult_digits[3] = 4;
free(mult_digits);
return 0;
}
Here we only used the first 4 elements, and ignored the final 4. That's just fine. In case you do over-allocate you would typically need to keep track of both the allocated length, and the in-use length. You can then add new items by increasing the in-use length, up until you reach the allocated length. The you need to reallocate a larger block. I guess that's what you are driving at.
The problem is your syntax. What you meant was: int *mult_digits = malloc(8 * sizeof(int));
After that, mult_digits[] = {1,2,3,4}; is wrong. You could, however,
mult_digits[0] = 1;
mult_digits[1] = 2;
mult_digits[2] = 3;
mult_digits[3] = 4;
But unless you have some reason to swim into the pointer deep end, you might just want to:
int mult_digits[] = {1, 2, 3, 4};
Edit: to help with applying this answer, here is a full modified function that compiles and runs:
#include <stdio.h>
int main(void)
{
int mult_digits[] = {1,2,3,4};
int size_mult = sizeof mult_digits / sizeof *mult_digits;
printf("Size of the array is %d\n", size_mult);
return 0;
}
in square brackets you must specify the number of elements needed, not the length in byte of the array. you can use malloc to do
int* multdigits = malloc(sizeof(int)*8);
mult_digits[0] = 1;
etc
(sorry if my syntax is wrong, i don't write c code from years!)
they're two ways to do the same thing. see "malloc" as the "new" operator.
Try
int main(void)
{
int mult_digits[] = {1,2,3,4};
int size_mult = sizeof mult_digits / sizeof int;
printf("Size of the array is %d\n", size_mult);
return 0;
}

Cannot return int array

I want to use only studio.h library to convert from decimal number to binary number by using an array to store remainder but the result is not correct, maybe i have problem with memory allocation or return value is wrong, please help me to check it.
Thank you so much!
#include <stdio.h>
int n = 0;
int* DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
void main(){
int *d1 = DecimalToBinary(5);
int *d2 = DecimalToBinary(10);
for(int i = n-1 ;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
for(int i = n-1 ;i>=0;i--)
printf(" %d",d2[i]);
}
You return a pointer to a local array. That local array is on the stack, and when the function returns the array goes out of scope and that stack memory will be reused when you call the next function. This means that the pointer will now point to some other data, and not the original array.
There are two solutions to this:
Declare the array in the function calling DecimalToBinary and pass it as an argument.
Create the array dynamically on the heap (e.g. with malloc) and return that pointer.
The problem with method 2 is that it might create a memory leak if you don't free the returned pointer.
As noted by Craig there is a third solution, to make the array static inside the function. However in this case it brings other and bigger problems than the two solutions I originally listed, and that's why I didn't list it.
There is also another serious problem with the code, as noted by Uchia Itachi, and that is that the array is indexed by a global variable. If the DecimalToBinary function is called with a too big number, or to many times, this global index variable will be to big for the array and will be out of bounds for the array.
Both the problem with dereferencing a pointer to an out-of-scope array and the indexing out of bounds leads to undefined behavior. Undefined behavior will, if you're lucky, just lead to the wrong result being printed. If you're unlucky it will cause the program to crash.
You are returning a pointer to a locally allocated array. It is allocated on the stack, and goes away when the function returns, leaving your pointer pointing to garbage.
You have a few options. You could pass an array in to fill:
void DecimalToBinary(int result[10],int number){
while(number!=0){
result[n++] = number%2;
number/=2;
}
return result;
}
// usage example:
int b[10];
DecimalToBinary(b, 42);
Or you could allocate an array on the heap:
int* DecimalToBinary(int number){
int *a = (int *)malloc(sizeof(int) * 10);
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
// usage example
int *b = DecimalToBinary(42);
free(b); // when finished with it
Or you could wrap the array in a struct:
typedef struct {
int b[10];
} result;
result DecimalToBinary(int number){
result r;
while(number!=0){
r.b[n++] = number%2;
number/=2;
}
return r;
}
// usage example
result r = DecimalToBinary(42);
If you do the malloc() option, do not forget to free() the returned data when you're done with it, otherwise it will hang around. This is called a memory leak. In more complex programs, it can lead to serious issues.
Note: By the way, if your number is larger than 1023 (10 binary digits), you'll overrun the array. You may also wish to explicitly stop once you've stored 10 digits, or pass the size of the array in, or compute the required size first and allocate that much space. Also, you will get some odd results if your number is negative, you might want to use number&1 instead of number%2.
Note 2: As noted elsewhere, you should make n local, or at the very least reinitalize it to 0 each time the function is called, otherwise it will just accumulate and eventually you'll go past the end of the array.
int[10] is not the same as int *; not only is the former created on the stack, it is a different type alltogether. You need to create an actual int * like so:
int *a = malloc (10 * sizeof (int));
Of course, don't forget to free() it after use!
What you can also do and what is commonly done in C is creating the array where it is called and provide a pointer to that array to the function, this way when the array is on the stack of the function that calls it and not in the function self. We also have to specify the size of the array on to that function, since the function cannot know to how many elements the pointer points to
void DecimalToBinary( int number, int* output, unsigned size ) {
/*adapt this to your liking*/
int i;
for ( i = 0; i < size && number != 0; i++) {
output[i] = number%2;
number/2;
}
}
and in you main function you would call it like this:
int array[10];
DecimalToBinary( 5, array, sizeof(array)/sizeof(array[0]));
now array has the same result as a would have had in your example.
The problem in your code lies here..
int * DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
The array a scope is only till this function. Once this function terminates, the memory allocated for this array will be released, either u need to use dynamic memory allocation or make array a global.
This is the correct program:
#include <stdio.h>
int n = 0;
int a[10] = {0};
int* DecimalToBinary(int number){
n = 0;
while(number!=0){
a[n++] = number%2;
number = number/2;
}
return a;
}
int main(){
int *d1;
int *d2;
int i;
d1 = DecimalToBinary(5);
for(i = n-1;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
d2 = DecimalToBinary(10);
for(i = n-1;i>=0;i--)
printf(" %d",d2[i]);
printf("\n");
}

How can I tell if a multi dimensional array has not been assigned to?

If I have two arrays likes this:
short** x;
short** y = functionThatReturnsAnArray();
In this situation sizeof(x) == sizeof(y).
Both are 4, I believe that this is because the outer array is simply an array of pointers and therefore doesn't actually have any RAM allocated to it.
How can I find out that x has not been assigned a value?
Thanks,
Joe
From a comment in your original post, what you mean is whether you can tell if a value has been assigned to a variable. We call that initialization. When a value hasn't been stored to a variable it's uninitialized, and that's bad, because you never know what might be in there, and no, you cannot check whether it has been initialized, so initialize it when you declare it.
sizeof(x) == sizeof(y) because they're declared as the same type (short**); their contents don't matter (sizeof is actually determined by the compiler, so it often can't know what's in it).
If you want to know whether the memory areas that each point to are zero, you'll need to do it manually (and you need to know how long each array is):
int x_empty = 1;
for(int i = 0; i < x_length_d1 && x_empty; i++) {
if(x[i] == NULL) {
// Handle a missing row however you want.
}
for(int j = 0; j < x_length_d2 && x_empty; j++) {
if(x[i][j] != 0) x_empty = 0;
}
}
The sizeof returns the size of short** (pointer to pointer to short) which appears to be 4 bytes in your system. If you allocate memory, you should know how many bytes have you allocated, and pass this value as well.
For example:
size_t size_allocated = 0;
short** y = functionThatReturnsAnArray(&size_allocated);
short ** functionThatReturnsAnArray(size_t * size) {
short ** buff;
size_t size_to_allocate = 5 * sizeof(short *);
buff = malloc(size_to_allocate);
if (!buff) {
*size = size_to_allocate;
}
else {
*size = 0;
}
return buff;
}
You cannot check if a variable has been assigned to. The value of an uninitialized variable is undefined IIRC. According to Assigning pointer to uninitialized variable changes it value? (found by Seth Carnegie), even accessing it causes undefined behaviour.
The solution? Explicitly assign a sentinel value and check for that. For pointers, NULL usually makes sense.

Resources