Checking whether two pointers are in the same block of memory - c

This is a homework question that I am confused on how to approach. There are restrictions as well were I cannot use /, %, or any loops. Given a method, it accepts two pointers of type int. Taking these two pointer I need to find whether they are in the same block of memory or in different block of memory. If case one I return 1 for them being in the same block if and 0 otherwise. So my thinking is that if two pointers are in the same block of memory that must mean they point to the same integer? Im not sure if this is correct any hint in the right direction would be greatly appreciated.
Thank you

Floris basically gave you the idea; here's my actual implementation for POSIX:
uintptr_t pagesz = getpagesize();
uintptr_t addr_one = (uintptr_t)ptr1;
uintptr_t addr_two = (uintptr_t)ptr2;
bool in_same_page = (addr_one & ~(pagesz - 1)) == (addr_two & ~(pagesz - 1));

Assuming that you know how large the blocks of memory are (I assume 1k (2^10)) you can subtract the smaller address from the larger and see if the difference is less than the block size -1.
int same_block(int x, int y){
int difference;
if(x > y){
difference = x - y;
} else {
difference = y - x;
}
if(difference < 1024){
return 1;
}
return 0;
}

Related

Convert read-only character array to float without null termination in C

I'm looking for a C function like the following that parses a length-terminated char array that expresses a floating point value and returns that value as a float.
float convert_carray_to_float( char const * inchars, int incharslen ) {
...
}
Constraints:
The character at inchars[incharslen] might be a digit or other character that might confuse the commonly used standard conversion routines.
The routine is not allowed to invoke inchars[incharslen] = 0 to create a z terminated string in place and then use the typical library routines. Even patching up the z-overwritten character before returning is not allowed.
Obviously one could copy the char array in to a new writable char array and append a null at the end, but I am hoping to avoid copying. My concern here is performance.
This will be called often so I'd like this to be as efficient as possible. I'd be happy to write my own routine that parses and builds up the float, but if that's the best solution, I'd be interested in the most efficient way to do this in C.
If you think removing constraint 3 really is the way to go to achieve high performance, please explain why and provide a sample that you think will perform better than solutions that maintain constraint 3.
David Gay's implementation, used in the *BSD libcs, can be found here: https://svnweb.freebsd.org/base/head/contrib/gdtoa/ The most important file is strtod.c, but it requires some of the headers and utilities. Modifying that to check the termination every time the string pointer is updated would be a bit of work but not awful.
However, you might afterwards think that the cost of the extra checks is comparable to the cost of copying the string to a temporary buffer of known length, particularly if the strings are short and of a known length, as in your example of a buffer packed with 3-byte undelimited numbers. On most architectures, if the numbers are no more than 8 bytes long and you were careful to ensure that the buffer had a bit of tail room, you could do the copy with a single 8-byte unaligned memory access at very little cost.
Here's a pretty good outline.
Not sure it covers all cases, but it shows most of the flow:
float convert_carray_to_float(char const * inchars, int incharslen)
{
int Sign = +1;
int IntegerPart = 0;
int DecimalPart = 0;
int Denominator = 1;
bool beforeDecimal = true;
if (incharslen == 0)
{
return 0.0f;
}
int i=0;
if (inchars[0] == '-')
{
Sign = -1;
i++;
}
if (inchars[0] == '+')
{
Sign = +1;
i++;
}
for( ; i<incharslen; ++i)
{
if (inchars[i] == '.')
{
beforeDecimal = false;
continue;
}
if (!isdigit(inchars[i]))
{
return 0.0f;
}
if (beforeDecimal)
{
IntegerPart = 10 * IntegerPart + (inchars[i] - '0');
}
else
{
DecimalPart = 10 * DecimalPart + (inchars[i] - '0');
Denominator *= 10;
}
}
return Sign * (IntegerPart + ((float)DecimalPart / Denominator));
}

Bus Error in C for Loop

I have a toy cipher program which is encountering a bus error when given a very long key (I'm using 961168601842738797 to reproduce it), which perplexes me. When I commented out sections to isolate the error, I found it was being caused by this innocent-looking for loop in my Sieve of Eratosthenes.
unsigned long i;
int candidatePrimes[CANDIDATE_PRIMES];
// CANDIDATE_PRIMES is a macro which sets the length of the array to
// two less than the upper bound of the sieve. (2 being the first prime
// and the lower bound.)
for (i=0;i<CANDIDATE_PRIMES;i++)
{
printf("i: %d\n", i); // does not print; bus error occurs first
//candidatePrimes[i] = PRIME;
}
At times this has been a segmentation fault rather than a bus error.
Can anyone help me to understand what is happening and how I can fix it/avoid it in the future?
Thanks in advance!
PS
The full code is available here:
http://pastebin.com/GNEsg8eb
I would say your VLA is too large for your stack, leading to undefined behaviour.
Better to allocate the array dynamically:
int *candidatePrimes = malloc(CANDIDATE_PRIMES * sizeof(int));
And don't forget to free before returning.
If this is Eratosthenes Sieve, then the array is really just flags. It's wasteful to use int if it's just going to hold 0 or 1. At least use char (for speed), or condense to a bit array (for minimal storage).
The problem is that you're blowing the stack away.
unsigned long i;
int candidatePrimes[CANDIDATE_PRIMES];
If CANDIDATE_PRIMES is large, this alters the stack pointer by a massive amount. But it doesn't touch the memory, it just adjusts the stack pointer by a very large amount.
for (i=0;i<CANDIDATE_PRIMES;i++)
{
This adjusts "i" which is way back in the good area of the stack, and sets it to zero. Checks that it's < CANDIDATE_PRIMES, which it is, and so performs the first iteration.
printf("i: %d\n", i); // does not print; bus error occurs first
This attempts to put the parameters for "printf" onto the bottom of the stack. BOOM. Invalid memory location.
What value does CANDIDATE_PRIMES have?
And, do you actually want to store all the primes you're testing or only those that pass? What is the purpose of storing the values 0 thru CANDIDATE_PRIMES sequentially in an array???
If what you just wanted to store the primes, you should use a dynamic allocation and grow it as needed.
size_t g_numSlots = 0;
size_t g_numPrimes = 0;
unsigned long* g_primes = NULL;
void addPrime(unsigned long prime) {
unsigned long* newPrimes;
if (g_numPrimes >= g_numSlots) {
g_numSlots += 256;
newPrimes = realloc(g_primes, g_numSlots * sizeof(unsigned long));
if (newPrimes == NULL) {
die(gracefully);
}
g_primes = newPrimes;
}
g_primes[g_numPrimes++] = prime;
}

Boolean array using "char"

I made an object that actually represents an array of 8 booleans stored in a char. I made it to learn something more about bitwise operators and about creating your own objects in C. So I've got two questions:
Can I be certain if the below code
always works?
Is this a good implementation to
make an object that can't get lost
in C, unless you release it
yourself.
The Code:
/*
* IEFBooleanArray.h
* IEFBooleanArray
*
* Created by ief2 on 8/08/10.
* Copyright 2010 ief2. All rights reserved.
*
*/
#ifndef IEFBOOLEANARRAY_H
#define IEFBOOLEANARRAY_H
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef char * IEFBooleanArrayRef;
void IEFBooleanArrayCreate(IEFBooleanArrayRef *ref);
void IEFBooleanArrayRelease(IEFBooleanArrayRef ref);
int IEFBooleanArraySetBitAtIndex(IEFBooleanArrayRef ref,
unsigned index,
int flag);
int IEFBooleanArrayGetBitAtIndex(IEFBooleanArrayRef ref,
unsigned index);
#endif
/*
* IEFBooleanArray.c
* IEFBooleanArray
*
* Created by ief2 on 8/08/10.
* Copyright 2010 ief2. All rights reserved.
*
*/
#include "IEFBooleanArray.h"
void IEFBooleanArrayCreate(IEFBooleanArrayRef *ref) {
IEFBooleanArrayRef newReference;
newReference = malloc(sizeof(char));
memset(newReference, 0, sizeof(char));
*ref = newReference;
}
void IEFBooleanArrayRelease(IEFBooleanArrayRef ref) {
free(ref);
}
int IEFBooleanArraySetBitAtIndex(IEFBooleanArrayRef ref, unsigned index, int flag) {
int orignalStatus;
if(index < 0 || index > 7)
return -1;
if(flag == 0)
flag = 0;
else
flag = 1;
orignalStatus = IEFBooleanArrayGetBitAtIndex(ref, index);
if(orignalStatus == 0 && flag == 1)
*ref = *ref + (int)pow(2, index);
else if(orignalStatus == 1 && flag == 0)
*ref = *ref - (int)pow(2, index);
return 0;
}
int IEFBooleanArrayGetBitAtIndex(IEFBooleanArrayRef ref, unsigned index) {
int result;
int value;
value = (int)pow(2, index);
result = value & *ref;
if(result == 0)
return 0;
else
return 1;
}
I'm more of an Objective-C guy, but I really want to learn C more. Can anyone request some more "homework" which I can improve myself with?
Thank you,
ief2
Don't check unsigned types with < 0, it's meaningless and causes warnings on some compilers.
Don't use unsigned types without specifying their size (unsigned int, unsigned char, etc).
If flag == 0 why are you setting it to 0?
I don't like abstracting the * away in a typedef, but it's not wrong by any means.
You don't need to call memset() to set a single byte to 0.
Using pow to calculate a bit offset is crazy. Check out the << and >> operators and use those instead
Fully parenthesize your if statement conditions or be prepared for debugging pain in your future.
If you use the bitwise operators & and | instead of arithmetic + and - in your SetBitAtIndex function, you won't need all those complicated if statements anyway.
Your GetBitAtIndex routine doesn't bounds check index.
From that list, #9 is the only one that means your program won't work in all cases, I think. I didn't exhaustively test it - that's just a first glance check.
pow(2,index) is among the more inefficient ways to produce a bit mask. I can imagine that using the Ackermann function could be worse, but pow() is pretty much on the slow side. You should use (1<<index) instead. Also, the C'ish way to set/clear a bit in a value looks different. Here's a recent question about this:
Simple way to set/unset an individual bit
If you want to munge bits in C in an efficient and portable way, then you really should have a look at the bit twiddling page, that everyone here will suggest to you if you mention "bits" somehow:
http://graphics.stanford.edu/~seander/bithacks.html
The following code sequence:
if(result == 0)
return 0;
else
return 1;
can be written as return (result != 0);, return resultor return !!result (if result should be forced to 0 or 1) . Though it's always a good idea to make an intent clear, most C programmer will prefer 'result result;' because in C this the way to make your intent clear. The if looks iffy, like a warning sticker saying "Original developer is a Java guy and knows not much about bits" or something.
newReference = malloc(sizeof(char));
memset(newReference, 0, sizeof(char));
malloc + memset(x,0,z) == calloc();
You have a way to report an error (invalid index) for IEFBooleanArraySetBitAtIndex but not for IEFBooleanArrayGetBitAtIndex. This is inconsistent. Make error reporting uniform, or the users of your library will botch error checking.
As for accessing bit #n in your char object, instead of using pow() function, you can use shifting and masking:
Set bit #n:
a = a | (1 << n);
Clear bit #n:
a = a & (~(1 << n));
Get bit #n:
return ((a >> n) & 1);
Nobody seems to be mentioning this (I am surprised), but... You can't tell me you're seriously doing malloc(sizeof(char))? That is a very small allocation. It doesn't make sense to make this a heap allocated object. Just declare it as char.
If you want to have some degree of encapsulation, you can do: typedef char IEFBoolArray; and make accessor functions to manipulate an IEFBoolArray. Or even do typedef struct { char value; } IEFBoolArray; But given the size of the data it would be sheer madness to allocate these one at a time on the heap. Have consumers of the type just declare it inline and use the accessors.
Further... Are you sure you want it to be char? You might get slightly better code generated if you promote that to something larger, like int.
In addition to Carl Norum points:
Don't save space in char such way unless you have to (i.e. you store a lot of bit values). It is much slower as you have to perform bitwise operations etc.
On most architectures you waste memory by mallocing char. One pointer takes 4 to 8 times more then char on most modern architectures and additionally you have data about the malloced chunk as it.
Probably static size is not the best approach as it inflexible. I wouldn't see any benefit of using speciall functions for it.
As of 3rd point something like:
typedef struct {
uint64_t size;
uint64_t *array;
}bitarray;
bitarray bitarray_new(uint64_t size) {
bitarray arr;
arr.size = size;
arr.array = calloc(size/8);
return arr;
}
void bitarray_free(bitarray arr) {
free(arr.array);
}
void bitarray_set(bitarray arr, uint64_t index, int bit) {
assert (index <= arr.size)
if (bit)
array[index/8] |= 1 << (index % 8);
else
array[index/8] ^= ~(1 << (index % 8));
}
void bitarray_get(bitarray arr, uint64_t index, int bit) {
assert (index <= arr.size)
return array[index/8] & 1 << (index % 8);
}
Copyright 2010 ief2. All rights reserved.
Actually they are not. You volontarly published them under cc-by-sa licence and only some right are reserved. Additionally you want us to read and modify the code so reserving all right is pointless.
(PS. I would advice against publishing trivial work under restrictive licences anyway - it does not look professionaly - unless you have legal issues to do so)
Is this a good implementation to make an object that can't get lost in C, unless you release it yourself.
Sorry?

storing known sequences in c

I'm working on Project Euler #14 in C and have figured out the basic algorithm; however, it runs insufferably slow for large numbers, e.g. 2,000,000 as wanted; I presume because it has to generate the sequence over and over again, even though there should be a way to store known sequences (e.g., once we get to a 16, we know from previous experience that the next numbers are 8, 4, 2, then 1).
I'm not exactly sure how to do this with C's fixed-length array, but there must be a good way (that's amazingly efficient, I'm sure). Thanks in advance.
Here's what I currently have, if it helps.
#include <stdio.h>
#define UPTO 2000000
int collatzlen(int n);
int main(){
int i, l=-1, li=-1, c=0;
for(i=1; i<=UPTO; i++){
if( (c=collatzlen(i)) > l) l=c, li=i;
}
printf("Greatest length:\t\t%7d\nGreatest starting point:\t%7d\n", l, li);
return 1;
}
/* n != 0 */
int collatzlen(int n){
int len = 0;
while(n>1) n = (n%2==0 ? n/2 : 3*n+1), len+=1;
return len;
}
Your original program needs 3.5 seconds on my machine. Is it insufferably slow for you?
My dirty and ugly version needs 0.3 seconds. It uses a global array to store the values already calculated. And use them in future calculations.
int collatzlen2(unsigned long n);
static unsigned long array[2000000 + 1];//to store those already calculated
int main()
{
int i, l=-1, li=-1, c=0;
int x;
for(x = 0; x < 2000000 + 1; x++) {
array[x] = -1;//use -1 to denote not-calculated yet
}
for(i=1; i<=UPTO; i++){
if( (c=collatzlen2(i)) > l) l=c, li=i;
}
printf("Greatest length:\t\t%7d\nGreatest starting point:\t%7d\n", l, li);
return 1;
}
int collatzlen2(unsigned long n){
unsigned long len = 0;
unsigned long m = n;
while(n > 1){
if(n > 2000000 || array[n] == -1){ // outside range or not-calculated yet
n = (n%2 == 0 ? n/2 : 3*n+1);
len+=1;
}
else{ // if already calculated, use the value
len += array[n];
n = 1; // to get out of the while-loop
}
}
array[m] = len;
return len;
}
Given that this is essentially a throw-away program (i.e. once you've run it and got the answer, you're not going to be supporting it for years :), I would suggest having a global variable to hold the lengths of sequences already calculated:
int lengthfrom[UPTO] = {};
If your maximum size is a few million, then we're talking megabytes of memory, which should easily fit in RAM at once.
The above will initialise the array to zeros at startup. In your program - for each iteration, check whether the array contains zero. If it does - you'll have to keep going with the computation. If not - then you know that carrying on would go on for that many more iterations, so just add that to the number you've done so far and you're done. And then store the new result in the array, of course.
Don't be tempted to use a local variable for an array of this size: that will try to allocate it on the stack, which won't be big enough and will likely crash.
Also - remember that with this sequence the values go up as well as down, so you'll need to cope with that in your program (probably by having the array longer than UPTO values, and using an assert() to guard against indices greater than the size of the array).
If I recall correctly, your problem isn't a slow algorithm: the algorithm you have now is fast enough for what PE asks you to do. The problem is overflow: you sometimes end up multiplying your number by 3 so many times that it will eventually exceed the maximum value that can be stored in a signed int. Use unsigned ints, and if that still doesn't work (but I'm pretty sure it does), use 64 bit ints (long long).
This should run very fast, but if you want to do it even faster, the other answers already addressed that.

Several basic C questions

I am a person who is trying to learn C, but I got stuck at a few points while doing my projects:
1) How exactly can I implement random integer generation? I have Googled and found the code for 0 to x generation with the code below, yet how about between 2 integers that I decide (like between X and Y)?
int random;
random = random(100);
2) How can I set a variable to NULL in the beginning (like in Java) and manipulate it if it is NULL? For instance I want to achieve the following:
int a = null;
if (a == null){
a = 3;
}
1)
int r = random(Y - X) + X;
2)
Integers can't be null in either C or Java. In C only pointers can be null, represented by pointing them to zero. However, I suggest you don't get into the whole pointer mess before getting the basics down.
1- How exactly can I implement a random integer generation [...]
See FAQ 13.15 and FAQ 13.16 -- the latter explicitly answers this question.
2- How can I set a variable null in the begining
For floats and integral types you assign them to the magic value 0. For pointers you can assign them to 0 (again) or the macro NULL.
To get the range you want (y-x) multiply each random numberby (y-x). To make them start at x and end at y add x to each number (already multiplied by (y-z)). Assume that y > x.
int i;
for (i = 0; i < NrOfNumers; i++)
{
randomNumberSequence[i] = randomNumberSequence[i]*(y-x) + x;
}
In C you often see the following:
int x = -1;
if (x == -1) { x = 3; } else { /* do nothing */ }
This assumes that the value type is actually unsigned or at least that -1 is not a valid value. You also can do:
#define UNINITIALIZED ((int8_t) -128) /* -128 has no inverse with 8-bit */
...
int8_t x = UNINITIALIZED;
if (x == UNINITIALIZED) { x = 3; } else { /* do nothing */ }

Resources