Как заставить поток читать правильный размер массива [duplicate]

Многие люди дали исправление, поэтому я расскажу об источнике проблемы.

Согласно журналу исключений:

Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
    at android.app.Activity.onCreate(Activity.java:1081)
    at android.support.v4.app.SupportActivity.onCreate(SupportActivity.java:66)
    at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:297)
    at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:84)
    at com.nut.blehunter.ui.DialogContainerActivity.onCreate(DialogContainerActivity.java:43)
    at android.app.Activity.performCreate(Activity.java:7372)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3147)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302) 
    at android.app.ActivityThread.-wrap12(Unknown Source:0) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891) 
    at android.os.Handler.dispatchMessage(Handler.java:108) 
    at android.os.Looper.loop(Looper.java:166)

Код, который вызвал исключение в Activity.java

    //Need to pay attention mActivityInfo.isFixedOrientation() and ActivityInfo.isTranslucentOrFloating(ta)
    if (getApplicationInfo().targetSdkVersion >= O_MR1 && mActivityInfo.isFixedOrientation()) {
        final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
        final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);
        ta.recycle();

        //Exception occurred
        if (isTranslucentOrFloating) {
            throw new IllegalStateException(
                    "Only fullscreen opaque activities can request orientation");
        }
    }

mActivityInfo.isFixedOrientation ():

        /**
        * Returns true if the activity's orientation is fixed.
        * @hide
        */
        public boolean isFixedOrientation() {
            return isFixedOrientationLandscape() || isFixedOrientationPortrait()
                    || screenOrientation == SCREEN_ORIENTATION_LOCKED;
        }
        /**
        * Returns true if the activity's orientation is fixed to portrait.
        * @hide
        */
        boolean isFixedOrientationPortrait() {
            return isFixedOrientationPortrait(screenOrientation);
        }

        /**
        * Returns true if the activity's orientation is fixed to portrait.
        * @hide
        */
        public static boolean isFixedOrientationPortrait(@ScreenOrientation int orientation) {
            return orientation == SCREEN_ORIENTATION_PORTRAIT
                    || orientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
                    || orientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
                    || orientation == SCREEN_ORIENTATION_USER_PORTRAIT;
        }

        /**
        * Determines whether the {@link Activity} is considered translucent or floating.
        * @hide
        */
        public static boolean isTranslucentOrFloating(TypedArray attributes) {
            final boolean isTranslucent = attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent, false);
            final boolean isSwipeToDismiss = !attributes.hasValue(com.android.internal.R.styleable.Window_windowIsTranslucent)
                                            && attributes.getBoolean(com.android.internal.R.styleable.Window_windowSwipeToDismiss, false);
            final boolean isFloating = attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);
            return isFloating || isTranslucent || isSwipeToDismiss;
        }

Согласно приведенному выше анализу кода, когда TargetSdkVersion> = 27 при использовании SCREEN_ORIENTATION_LANDSCAPE, SCREEN_ORIENTATION_PORTRAIT, и другие связанные атрибуты, использование атрибутов темы windowIsTranslucent, windowIsFloating и windowSwipeToDismiss вызовет исключение.

После обнаружения проблемы вы можете изменить TargetSdkVersion или удалить связанные атрибуты темы в соответствии с вашими нуждается.

729
задан Peter Mortensen 28 February 2013 в 16:16
поделиться

16 ответов

Исполнительное резюме:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

Чтобы определить размер вашего массива в байтах, вы можете использовать оператор sizeof:

int a[17];
size_t n = sizeof(a);

На моем компьютере, ints имеют длину 4 байта, поэтому n равно 68.

Чтобы определить количество элементов в массиве, мы можем разделить общий размер массива на размер элемента массива. Вы можете сделать это с типом, например:

int a[17];
size_t n = sizeof(a) / sizeof(int);

и получить правильный ответ (68/4 = 17), но если тип a изменился, у вас будет неприятная ошибка, если вы также забыли изменить sizeof(int).

Таким образом, предпочтительным делителем является sizeof(a[0]), размер элемента zeroeth массива.

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

Еще одно преимущество что теперь вы можете легко параметризовать имя массива в макросе и получить:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);
922
ответ дан Jens 31 August 2018 в 20:17
поделиться

Для многомерных массивов это немного сложнее. Часто люди определяют явные макроконстанты, т. Е.

#define g_rgDialogRows   2
#define g_rgDialogCols   7

static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{
    { " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },
    { " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};

. Но эти константы могут быть вычислены и во время компиляции с помощью sizeof :

#define rows_of_array(name)       \
    (sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \
    (sizeof(name[0]) / sizeof(name[0][0]))

static char* g_rgDialog[][7] = { /* ... */ };

assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);

Примечание что этот код работает на C и C ++. Для массивов с более чем двумя измерениями используйте

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])

и т. Д., Ad infinitum.

13
ответ дан Andreas Spindler 31 August 2018 в 20:17
поделиться
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))
9
ответ дан Andy Nugent 31 August 2018 в 20:17
поделиться
int size = (&arr)[1] - arr;

Проверьте эту ссылку для объяснения

32
ответ дан Arjun Sreedharan 31 August 2018 в 20:17
поделиться

Если вы действительно хотите сделать это, чтобы передать свой массив, я предлагаю реализовать структуру для хранения указателя на тип, который вам нужен, массив и целое число, представляющее размер массива. Затем вы можете передать это своим функциям. Просто присвойте значение переменной массива (указатель на первый элемент) этому указателю. Затем вы можете пойти Array.arr[i], чтобы получить i-й элемент, и использовать Array.size, чтобы получить количество элементов в массиве.

Я включил для вас некоторый код. Это не очень полезно, но вы можете расширить его с большим количеством функций. Если честно, если это то, что вам нужно, вы должны прекратить использовать C и использовать другой язык с этими встроенными функциями.

/* Absolutely no one should use this...
   By the time you're done implementing it you'll wish you just passed around
   an array and size to your functions */
/* This is a static implementation. You can get a dynamic implementation and 
   cut out the array in main by using the stdlib memory allocation methods,
   but it will work much slower since it will store your array on the heap */

#include <stdio.h>
#include <string.h>
/*
#include "MyTypeArray.h"
*/
/* MyTypeArray.h 
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/
typedef struct MyType
{
   int age;
   char name[20];
} MyType;
typedef struct MyTypeArray
{
   int size;
   MyType *arr;
} MyTypeArray;

MyType new_MyType(int age, char *name);
MyTypeArray newMyTypeArray(int size, MyType *first);
/*
#endif
End MyTypeArray.h */

/* MyTypeArray.c */
MyType new_MyType(int age, char *name)
{
   MyType d;
   d.age = age;
   strcpy(d.name, name);
   return d;
}

MyTypeArray new_MyTypeArray(int size, MyType *first)
{
   MyTypeArray d;
   d.size = size;
   d.arr = first;
   return d;
}
/* End MyTypeArray.c */


void print_MyType_names(MyTypeArray d)
{
   int i;
   for (i = 0; i < d.size; i++)
   {
      printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);
   }
}

int main()
{
   /* First create an array on the stack to store our elements in.
      Note we could create an empty array with a size instead and
      set the elements later. */
   MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")};
   /* Now create a "MyTypeArray" which will use the array we just
      created internally. Really it will just store the value of the pointer
      "arr". Here we are manually setting the size. You can use the sizeof
      trick here instead if you're sure it will work with your compiler. */
   MyTypeArray array = new_MyTypeArray(2, arr);
   /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */
   print_MyType_names(array);
   return 0;
}
3
ответ дан bartimar 31 August 2018 в 20:17
поделиться

Способ sizeof - это правильный путь iff , который вы имеете в виду массивы, не полученные в качестве параметров. Массив, отправленный как параметр функции, рассматривается как указатель, поэтому sizeof вернет размер указателя вместо массива.

Таким образом, внутри функций этот метод не работает. Вместо этого всегда передавайте дополнительный параметр size_t size, указывающий количество элементов в массиве.

Тест:

#include <stdio.h>
#include <stdlib.h>

void printSizeOf(int intArray[]);
void printLength(int intArray[]);

int main(int argc, char* argv[])
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6 };

    printf("sizeof of array: %d\n", (int) sizeof(array));
    printSizeOf(array);

    printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
    printLength(array);
}

void printSizeOf(int intArray[])
{
    printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}

void printLength(int intArray[])
{
    printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}

Выход (в 64-разрядной ОС Linux):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2

Вывод (в 32-разрядной ОС Windows):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
621
ответ дан Elideb 31 August 2018 в 20:17
поделиться

Вы можете использовать оператор sizeof, но он не будет работать для функций, потому что для ссылки на указатель вы можете сделать следующее, чтобы найти длину массива:

len = sizeof(arr)/sizeof(arr[0])

Код, первоначально найденный здесь : C программа для поиска числа элементов в массиве

20
ответ дан Joncom 31 August 2018 в 20:17
поделиться

Функция sizeof возвращает количество байтов, которое используется вашим массивом в памяти. Если вы хотите вычислить количество элементов в вашем массиве, вы должны разделить это число на тип переменной sizeof массива. Скажем, int array[10];, если целочисленное целое число переменной на вашем компьютере равно 32 бит (или 4 байта), чтобы получить размер вашего массива, вы должны сделать следующее:

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);
1
ответ дан K1.K 31 August 2018 в 20:17
поделиться

Вы можете использовать оператор &. Вот исходный код:

#include<stdio.h>
#include<stdlib.h>
int main(){

    int a[10];

    int *p; 

    printf("%p\n", (void *)a); 
    printf("%p\n", (void *)(&a+1));
    printf("---- diff----\n");
    printf("%zu\n", sizeof(a[0]));
    printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0])));


    return 0;
};

Вот пример вывода

1549216672
1549216712
---- diff----
4
The size of array a is 10
1
ответ дан M.M 31 August 2018 в 20:17
поделиться

Стоит отметить, что sizeof не помогает при работе со значением массива, которое распалось на указатель: хотя он указывает на начало массива, компилятору он совпадает с указателем на один элемент этого массива. Указатель не «помнит» ничего о массиве, который использовался для его инициализации.

int a[10];
int* p = a;

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
104
ответ дан Magnus Hoff 31 August 2018 в 20:17
поделиться

Лучший способ сохранить эту информацию, например, в структуре:

typedef struct {
     int *array;
     int elements;
} list_s;

Реализовать все необходимые функции, такие как создание, уничтожение, проверка равенства и все остальное, что вам нужно. Это легче передать в качестве параметра.

3
ответ дан Paulo Pinheiro 31 August 2018 в 20:17
поделиться

Использование:

int a=[10] = {1, 2, 3, 4, 5};
int n = sizeof(a);
printf("%d", n);

Выход:

5

Причина: вычисляет количество элементов, хранящихся в массиве, а не количество свободных пространств, выделенных ему.

18
ответ дан Peter Mortensen 31 August 2018 в 20:17
поделиться
-1
ответ дан Pygirl 31 August 2018 в 20:17
поделиться
sizeof(array) / sizeof(array[0])
10
ответ дан Ted Percival 31 August 2018 в 20:17
поделиться

@ Магнус: Стандарт определяет sizeof как уступающий количеству байтов в объекте, а sizeof (char) всегда один.

Edit: ANSI C ++ standard section 5.3.3 Sizeof:

Оператор sizeof дает количество байтов в объекте представление его операнда. [...] sizeof (char), sizeof (signed char) и sizeof (unsigned char) равны 1; результат sizeof, примененный к любому другому фундаментальному типу, определяется реализацией.

Раздел 1.6 Модель памяти C ++:

Фундаментальная единица хранения в C ++ модель памяти - это байт. Байт, по крайней мере, достаточно большой, чтобы содержать любой элемент базового набора символов выполнения и состоит из непрерывной последовательности бит, число которой определяется реализацией.

4
ответ дан Tim Cooper 31 August 2018 в 20:17
поделиться

Размерный «трюк» - это лучший способ, который я знаю, с одним маленьким, но (для меня это серьезный питомец) важное изменение в использовании круглых скобок.

Поскольку запись в Википедии делает clear, C sizeof не является функцией; это оператор. Таким образом, он не требует скобок вокруг своего аргумента, если аргумент не является именем типа. Это легко запомнить, так как он делает аргумент похожим на выражение cast, которое также использует скобки.

So: Если у вас есть следующее:

int myArray[10];

Вы можете найти количество элементов с таким кодом:

size_t n = sizeof myArray / sizeof *myArray;

Это, для меня, намного легче, чем альтернатива с круглыми скобками. Я также предпочитаю использовать звездочку в правой части деления, поскольку она более кратка, чем индексация.

Конечно, это тоже время компиляции, поэтому нет необходимости беспокоиться о том, разделение, влияющее на производительность программы. Поэтому используйте эту форму, где бы вы ни были.

Всегда лучше использовать sizeof для фактического объекта, если он у вас есть, а не на типе, поскольку вам не нужно беспокоиться о том, чтобы сделать ошибку и указать неверный тип.

Например, скажем, у вас есть функция, которая выводит некоторые данные в виде потока байтов, например, по сети. Назовем функцию send() и сделаем в качестве аргументов указатель на отправляемый объект и количество байтов в объекте. Итак, прототип становится:

void send(const void *object, size_t size);

И тогда вам нужно отправить целое число, поэтому вы его кодируете следующим образом:

int foo = 4711;
send(&foo, sizeof (int));

Теперь вы ввели тонкий способ стрельбы в ногу, указав тип foo в двух местах. Если кто-то меняет, а другой - нет, код прерывается. Таким образом, всегда делайте это так:

send(&foo, sizeof foo);

Теперь вы защищены. Конечно, вы дублируете имя переменной, но это имеет высокую вероятность взлома способом, который может обнаружить компилятор, если вы его измените.

36
ответ дан unwind 31 August 2018 в 20:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: