I'm trying to convert an 8 bit array into into a number from 0-255 by adding values depending on the position in the field.
if I use
int array[8]={
0,1,1,0,0,0,0,1
};
int *p = array;
int i;
for (i = 0; i<8; i++){
if(p[i]!=0){
a = pow(2,i);
printf("%i\n",a);
}
};
I get:
2
4
128
as results, which would be right so far.
but if I use
int array[8]={
0,1,1,0,0,0,0,1
};
int *p = array;
int i;
for (i = 0; i<8; i++){
if(p[i]!=0){
a = a + pow(2,i);
printf("%i\n",a);
}
};
I instead get:
2686758
2686762
2686890
when I expect:
134
What am I doing wrong?
You have not initialised a to 0.
The following should work
int array[8]={
0,1,1,0,0,0,0,1
};
int *p = array;
int i;
a = 0 // << Initialise a
for (i = 0; i<8; i++){
if(p[i]!=0){
a = a + pow(2,i);
printf("%i\n",a);
}
};
You always need to provide an initial value for your variables. Otherwise, you can expect them to start with ANY value.
In the second piece of code you are accumulating a=a+pow(2,i) and it is here where the first time a is used, it will contain some undetermined value.
The problem is in the statement: a = a + pow(2,1);
a has indeterminate value because it has not been initialized and you are using it in arithmetic operation.
pow is intended to compute the exponential function of two real (not integer) values. So you could use it to compute π3/2. It is really not ideal for computing integer powers of 2. Much simpler and faster (though possibly less readable until you get used to it) is to write 2i as (1UL << i). However, in this particular case you don't need either of those. You could just do the following:
int a = 0;
for (int index = 0, value = 1; index < 8; ++index, value *= 2)
if (p[i]) a += value;
or even more directly
int a = 0;
for (int value = 1, *p = array; value < 256; value *= 2, ++p)
if (*p) a += value;
(As has been mentioned, the problem in your original was not actually the use of pow but rather the absence of the initialization int a = 0.)
alright ! i fixed it by adding =0; to the int a;intitialization
Tanks !
Related
I want to use avgs as a pointer, but how would I modify the code below to use it correctly? I am computing the average of an int array, given the starting pointer and the length..
int compute_average(int *avgs, int len) {
int sum = 0;
for (int i = 0; i < len; i++)
sum += avgs[i];
return (int)(sum / len);
}
I tried writing it like this, but it didn't work correctly:
do {sum += *avgs;}
while(*(avgs++)!='\0');
Testing that your pointer doesn't point into a \0 is fine when you work with strings. Here you have an array of ints and a length so you can't really use a destination point to stop incrementing the pointer. You need to use that len just like in your first snippet but instead of accessing the ith element of your array, you can still increment the pointer. Something like this :
int compute_average(int *avgs, int len) {
int sum = 0;
for (int i = 0; i < len; i++)
sum += *(avgs++);
return (int)(sum / len);
}
#include <iostream>
using namespace std;
int* computeSquares(int& n)
{
int arr[10];
n = 10;
for (int k = 0; k < n; k++)
arr[k] = (k + 1) * (k + 1);
return arr;
}
void f()
{
int junk[100];
for (int k = 0; k < 100; k++)'
junk[k] = 123400000 + k;
}
int main()
{
int m;
int* ptr = computeSquares(m);
f();
for (int i = 0; i < m; i++) {
cout << ptr[i] << ' ';
}
}
The above code should print:
1 4 9 16 25 36 49 64 81 100
However, it instead prints random integer values that don't make any sense, at least after the first one. After running the code through the debugger, the ptr address is deleted right after the first run of the for loop in the main method and I cannot fathom why. Additionally, I have no idea what the purpose of the f() method is, I don't think it should change anything but when I remove it from the main the first value returns accurately (everything after is still wrong.) What is going on?
Try this:
int *computeSquares(int &n) {
int *arr = new int[10];
n = 10;
for (int k = 0; k < n; k++)
arr[k] = (k + 1) * (k + 1);
return arr;
}
The memory of "int arr[10]" is released after computeSquares finished running.
You are getting this result because you are misunderstanding basic language features. In addition to MsrButterfly's answer, who pointed out the most important problem already, let me please give you the following advices:
forget about using raw pointers; it is dangerous practice, very hard to maintain and extend, and will for sure lead you to write code with memory leaks. You will be better off having a look at some STL documentation which possesses e.g. the std::vector container that you could use instead of your array arr
your computeSquares method is dangerous in the sense that you take a variable n a argument which should be your array's size. In your method, you first define arr with a hard-coded size of 10 and then you set n = 10; I'd suggest you avoid that kind of constructs as you have in this case to maintain two variables that depend on that number 10.
I'm trying to fill an array with numbers 1111 to 8888, with each integer in the number being between 1 and 8 in c++. However, when I run it, it's only outputting large negative numbers indicating an error. I honestly have clue what the error is so it would be appreciated if you could help me out. Thanks!
int fillArray()
{
int arrayPosition;
int guesses[4096];
arrayPosition = 0;
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses[arrayPosition] = ((i * 1000) + (j * 100) + (k *10) + m);
cout << guesses[arrayPosition];
arrayPosition++;
}
return guesses[4096];
}
Your return type is wrong. int fillArray(), but you're trying to return an int[4096] that was declared on the stack... What you're actually doing with return guesses[4096]; is returning the first memory location after your array in memory, which is probably just garbage, hence your issue with large negative numbers.
You can fix it by allocating your array in the heap, and returning a pointer to the start of that array:
int * fillArray()
{
int arrayPosition;
int * guesses = new int[4096];
// other stuff stays the same...
return guesses;
}
However, since your function is called fillArray, it would make more sense to pass in an array and fill it rather than creating the array in the function. (If you wanted to do that, might call it something like make_1_to_8_array instead, to make it more clear that you're constructing something that will need to be deleted later.) Giving an int* as the first argument would allow you to pass in the base address of your array that you want filled:
void fillArray(int * guesses)
{
int arrayPosition;
// other stuff stays the same...
}
Or, if you want to verify that the you're using an array of the exact size:
void fillArray(int (&guesses)[4096])
{
int arrayPosition;
// other stuff stays the same...
}
Note that the function now returns void since you just update the array that was passed in, and you don't need to return anything new.
Your for-loops look correct, but your array handling is off, as is highlighted by other answers.
It is more usual in C++ to use std::vector and to pass this in by reference as an argument. This saves you having to handle memory allocations and deallocations. Here's an example, including the output in the for-loops:
#include <iostream>
#include <vector>
int fillArray(std::vector<int>& guesses)
{
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses.push_back((i * 1000) + (j * 100) + (k * 10) + m);
std::cout << guesses.back() << std::endl;
}
return guesses.back();
}
int main()
{
std::vector<int> guesses;
std::cout << fillArray(guesses) << std::endl;
}
You are creating your array locally then attempting to return it. If you try printing (to debug) out the result of your array prior to returning, you will see it is ok. However, once you return, the array is no linger valid. Try passing in an array into your function instead.
I'm having trouble understanding what the difference between these two code snippets is:
// out is of type char* of size N*D
// N, D are of type int
for (int i=0; i!=N; i++){
if (i % 1000 == 0){
std::cout << "i=" << i << std::endl;
}
for (int j=0; j!=D; j++) {
out[i*D + j] = 5;
}
}
This code runs fine, even for very big data sets (N=100000, D=30000). From what I understand about pointer arithmetic, this should give the same result:
for (int i=0; i!=N; i++){
if (i % 1000 == 0){
std::cout << "i=" << i << std::endl;
}
char* out2 = &out[i*D];
for (int j=0; j!=D; j++) {
out2[j] = 5;
}
}
However, the latter does not work (it freezes at index 143886 - I think it segfaults, but I'm not 100% sure as I'm not used to developing on windows) for a very big data set and I'm afraid I'm missing something obvious about how pointer arithmetic works. Could it be related to advancing char*?
EDIT: We have now established that the problem was an overflow of the index (i.e. (i*D + j) >= 2^32), so using uint64_t instead of int32_t fixed the problem. What's still unclear to me is why the first above case would run through, while the other one segfaults.
N * D is 3e9; that doesn't fit in a 32 bit int.
When using N as size of array, why use int?
does a negative value of an array has any logical meaning?
what do you mean "doesn't work"?
just think of pointers as addresses in memory and not as 'objects'.
char*
void*
int*
are all pointers to memory addresses, and so are exactly the same, when are defined or passes into a function.
char * a;
int* b = (char*)a;
void* c = (void*)b;
a == b == c;
The difference is that when accessing a, a[i], the value that is retrieved is the next sizeof(*a) bytes from the address a.
And when using ++ to advance a pointer the address that the pointer is set to is advanced by
sizeof(pointer_type) bytes.
Example:
char* a = 1;
a++;
a is now 2.
((int*)a)++;
a is now 6.
Another thing:
char* a = 10;
char* b = a + 10;
&(a[10]) == b
because in the end
a[10] == *((char*)(a + 10))
so there should not be a problem with array sizes in your example, because the two examples are the same.
EDIT
Now note that there is not a negative memory address so accessing an array with a signed negative value will convert the value to positive.
int a = -5;
char* data;
data[a] == data[MAX_INT - 5]
For that reason it might be that (when using sign values as array sizes!) your two examples will actually not get the same result.
Version 1
for (int i=0; i!=N; i++) // i starts at 0 and increments until N. Note: If you ever skip N, it will loop forever. You should do < N or <= N instead
{
if (i % 1000 == 0) // if i is a multiple of 1000
{
std::cout << "i=" << i << std::endl; // print i
}
for (int j=0; j!=D; j++) // same as with i, only j is going to D (same problem, should be < or <=)
{
out[i*D + j] = 5; // this is a way of faking a 2D array by making a large 1D array and doing the math yourself to offset the placement
}
}
Version 2
for (int i=0; i!=N; i++) // same as before
{
if (i % 1000 == 0) // same as before
{
std::cout << "i=" << i << std::endl; // same as before
}
char* out2 = &out[i*D]; // store the location of out[i*D]
for (int j=0; j!=D; j++)
{
out2[j] = 5; // set out[i*D+j] = 5;
}
}
They are doing the same thing, but if out is not large enough, they will both behave in an undefined manner (and likely crash).
#include<stdio.h>
#include<conio.h>
unsigned * bin(unsigned n) {
unsigned a[16];
int i = 0, j = 0;
for (i = 0; i < 16; i++) {
a[i] = n & 0x1;
n = n >> 1;
}
return a;
}
void main() {
unsigned n = 5;
int i = 0;
unsigned * a = bin(n);
for (i = 15; i >= 0; i--) {
printf("%d\n", (*(a + i)));
}
getch();
}
Please help this binary conversion does not work. I'm trying to calculate x^n using binary conversion.
can anybode help??
You are returning a pointer to a local variable. This variable is stored on the stack, and will not be valid after the function returns.
Dereferencing this pointer will lead to undefined behavior.
The solution is to either make the variable static, or pass in the array as an argument to the function, or (as noted in a comment by James Kanze) use a type that copies the contents.
you can not return a local array defined in the function in this way.
The content of the array will be erased when the function finish the execution.
instead of using
unsigned a[16];
you can use the following:
unsigned *a =malloc(16 * (sizeof *a));
And do not forget in your main to free the memory allocated for a when the a array become useless in your program. you can free the array with:
free(a);
Actually, this is a typical case where using new (or malloc) is a pretty bad choice. However, as others have said, returning a pointer to a local array is bad.
Instead, pass in an array:
void bin(unsigned n, unsigned a[]) {
int i = 0;
for (i = 0; i < 16; i++) {
a[i] = n & 0x1;
n = n >> 1;
}
}
and in main:
unsigned a[16];
bin(n, a);
Now you have no need to allocate or return an array from bin.